2012-01-06 2 views
6

У меня есть спецификатор типа, возвращаемый методом method_copyReturnType(). В среде выполнения GNU, поставляемой с GCC, существуют различные методы работы с таким спецификатором типа, как objc_sizeof_type(), objc_alignof_type() и другими.Как интерпретировать спецификатор типа object-c (например, возвращаемый методом method_copyReturnType())?

При использовании среды выполнения Apple таких методов нет.

Как я могу интерпретировать строку спецификатора типа (например, получить размер типа), используя время выполнения Apple без, реализуя для меня переключатель if/else или case?

[обновление]

Я не могу использовать компании Apple Foundation.

ответ

2

afaik, вам нужно испечь эту информацию в своем двоичном формате. просто создайте функцию, которая возвращает sizeof и alignof в структуре, поддерживает типы, которые вы должны поддерживать, затем вызывайте эту функцию (или метод класса) для информации.

В приведенной ниже программе показано, что многие из примитивов - это всего лишь один символ. Таким образом, основная часть реализации функции может быть коммутатором.

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; 
    } 
} 

и вы могли бы использовать это в качестве отправной точки:

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

Итак, ответ: нет способа сделать это, не реализуя его самостоятельно. Верный? –

+0

@Tilo Я сделал некоторые глупые вещи со временем выполнения - нет бесплатного решения, о котором я знаю, но решение в моем ответе может быть реализовано довольно легко, если вы знаете типы, которые вы должны поддерживать. Конечно, вы также можете подождать и посмотреть, если вы получите более подходящий ответ. – justin

+0

@Tilo - добавлено демо для этого – justin

5

Я считаю, что вы ищете NSGetSizeAndAlignment:

Получает фактический размер и выровненный размер закодированный тип.

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

Обсуждение
Получает фактический размер и выровненный размер первого типа данных, представленного typePtr и возвращает указатель на позицию следующего типа данных в typePtr.

Это функция фонда, а не часть базового времени выполнения, что, вероятно, поэтому не нашло его.

UPDATE: Хотя первоначально не говоря уже о том, что вы используете Cocotron, он также доступен здесь. Вы можете найти его в Фонде Кокотрона, в NSObjCRuntime.m.

Очевидно, что это намного лучше, чем опрокидывание собственного, поскольку вы можете доверять ему, чтобы всегда правильно обрабатывать строки, созданные его собственной средой выполнения, в маловероятном случае, когда символы кодировки должны измениться.

По какой-то причине, однако, он не может обрабатывать цифровые элементы строки подписи метода (которая, по-видимому, имеет что-то делать с смещениями в памяти). This improved version, by Mike Ash будет делать это:

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 хорошая находка, Josh – justin

+0

Проблема в том, что у меня нет общего доступа к Apple Foundation, поскольку она существует только для продуктов Apple :). Проект, над которым я работаю, - это Cocotron (альтернатива Фонду). Поэтому я не могу использовать методы Foundation. –

+0

@Tilo: Рамка, которую вы используете, - это довольно большое условие **, которое, вероятно, вы должны были включить в свой вопрос для начала. Однако такая же функция доступна в Cococtron. См. Мое редактирование. –