Как интерпретировать спецификатор типа target-c (например, возвращаемый методом method_copyReturnType ())? - PullRequest
6 голосов
/ 06 января 2012

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

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

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

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

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

Ответы [ 2 ]

5 голосов
/ 07 января 2012

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

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

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

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

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

ОБНОВЛЕНИЕ: Хотя вы изначально не упоминали, что используете Cocotron, он также доступен там.Вы можете найти его в Cocotron's Foundation, в NSObjCRuntime.m .

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

По какой-то причине, однако, он не может обрабатывать цифровые элементы строки сигнатуры метода (которые предположительно имеют отношение к смещениям в памяти). Эта улучшенная версия от 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;
}
2 голосов
/ 06 января 2012

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));
            ...
...