2012-01-06 28 views
6

Dado que tengo un especificador de tipo devuelto por method_copyReturnType(). En el tiempo de ejecución de GNU entregado con GCC hay varios métodos para trabajar con un especificador de tipo como objc_sizeof_type(), objc_alignof_type() y otros.Cómo interpretar el especificador de tipo object-c (por ejemplo, devuelto por method_copyReturnType())?

Al usar el tiempo de ejecución de Apple, no existen tales métodos.

¿Cómo puedo interpretar una cadena especificador de tipo (por ejemplo, obtener el tamaño de un tipo) con el tiempo de ejecución de Apple sin la implementación de un if/else o caja de conmutación para mí?

[Actualización]

no soy capaz de utilizar la Fundación de Apple.

Respuesta

2

afaik, necesitarás hornear esa información en tu binario. simplemente cree una función que devuelva el tamaño de y alinee en una estructura, admite los tipos que debe soportar y luego llame a esa función (o método de clase) para la información.

El siguiente programa muestra que muchas de las primitivas son solo un carácter. Entonces, la mayor parte de la implementación de la función podría ser un cambio.

static void test(SEL sel) { 
    Method method = class_getInstanceMethod([NSString class], sel); 

    const char* const type = method_copyReturnType(method); 

    printf("%s : %s\n", NSStringFromSelector(sel).UTF8String, type); 

    free((void*)type); 
} 

int main(int argc, char *argv[]) { 
    @autoreleasepool { 

     test(@selector(init)); 
     test(@selector(superclass)); 
     test(@selector(isEqual:)); 
     test(@selector(length)); 

     return 0; 
    } 
} 

y, a continuación, podría utilizar esto como un punto de partida:

typedef struct t_pair_alignof_sizeof { 
    size_t align; 
    size_t size; 
} t_pair_alignof_sizeof; 

static t_pair_alignof_sizeof MakeAlignOfSizeOf(size_t align, size_t size) { 
    t_pair_alignof_sizeof ret = {align, size}; 
    return ret; 
} 

static t_pair_alignof_sizeof test2(SEL sel) { 
    Method method = class_getInstanceMethod([NSString class], sel); 
    const char* const type = method_copyReturnType(method); 
    const size_t length = strlen(type); 

    if (1U == length) { 
     switch (type[0]) { 
      case '@' : 
       return MakeAlignOfSizeOf(__alignof__(id), sizeof(id)); 
      case '#' : 
       return MakeAlignOfSizeOf(__alignof__(Class), sizeof(Class)); 
      case 'c' : 
       return MakeAlignOfSizeOf(__alignof__(signed char), sizeof(signed char)); 
      ... 
+0

Así que la respuesta es: No hay forma de hacerlo sin implementarlo yo solo. ¿Correcto? –

+0

@Tilo He hecho algunas tonterías con el tiempo de ejecución, no hay una solución gratuita que yo sepa, pero la solución en mi respuesta puede implementarse bastante fácilmente si conoce los tipos que debe admitir. Por supuesto, también puede esperar y ver si obtiene una respuesta más adecuada. – justin

+0

@Tilo - agregué una demostración para este – justin

5

Creo que usted está buscando NSGetSizeAndAlignment:

Obtiene el tamaño real y el tamaño de alineado un tipo codificado

const char * NSGetSizeAndAlignment (
    const char *typePtr, 
    NSUInteger *sizep, 
    NSUInteger *alignp 
);

Discusión
obtiene el tamaño real y el tamaño alineados del primer tipo de datos representado por typePtr y devuelve un puntero a la posición del siguiente tipo de datos en typePtr.

Esta es una función de base, no parte del tiempo de ejecución base, que es probablemente la razón por la que no lo encontraste.

ACTUALIZACIÓN: Aunque no ha mencionado al principio que está utilizando Cocotron, que también está disponible allí. Puede encontrarlo en Cocotron's Foundation, en NSObjCRuntime.m.

Obviamente, esto es mucho mejor que rodar el suyo, ya que puede confiar en que siempre maneja correctamente las cadenas generadas por su propio tiempo de ejecución en el improbable caso de que los caracteres de codificación cambien.

Por alguna razón, sin embargo, no puede manejar los elementos de dígitos de una cadena de firma de método (que presumiblemente tiene algo que ver con las compensaciones en la memoria). This improved version, by Mike Ash lo hará:

static const char *SizeAndAlignment(const char *str, NSUInteger *sizep, NSUInteger *alignp, int *len) 
{ 
    const char *out = NSGetSizeAndAlignment(str, sizep, alignp); 
    if(len) 
     *len = out - str; 
    while(isdigit(*out)) 
     out++; 
    return out; 
} 
+0

+1 buen hallazgo, Josh – justin

+0

El problema es que no tengo acceso general a la Fundación Apple, ya que solo existe para los productos de Apple :). El proyecto en el que estoy trabajando es Cocotron (una alternativa a la Fundación). Entonces no puedo usar los métodos de Foundation. –

+0

@Tilo: el marco que está utilizando es ** una condición bastante grande ** que probablemente debería haber incluido en su pregunta para empezar. La misma función, sin embargo, está disponible en Cococtron. Ver mi edición –

Cuestiones relacionadas