如何解释objective-c类型说明符(例如,由method_copyReturnType()返回)?

时间:2012-01-06 09:28:34

标签: objective-c objective-c-runtime

鉴于我有一个由method_copyReturnType()返回的类型说明符。在随GCC提供的GNU运行时中,有多种方法可以使用类似objc_sizeof_type()objc_alignof_type()等类型说明符。

使用Apple运行时时,没有这样的方法。

如何使用Apple运行时解释类型说明符字符串(例如获取类型的大小)而不为自己实现if / else或case开关?

[更新]

我无法使用Apple Foundation。

2 个答案:

答案 0 :(得分:5)

我相信你正在寻找NSGetSizeAndAlignment

  

获得编码类型的实际大小和对齐大小。

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

<强>讨论
  获得typePtr表示的第一个数据类型的实际大小和对齐大小,并返回指向typePtr中下一个数据类型位置的指针。

这是一个基础功能,不是基本运行时的一部分,这可能是你找不到它的原因。

更新: 虽然您最初没有提到您正在使用Cocotron,但它也可以在那里使用。您可以在NSObjCRuntime.m中的Cocotron基金会找到它。

显然,这比滚动自己要好得多,因为您可以信任它始终正确处理由自己的运行时生成的字符串,万一编码字符应该更改。

然而,出于某种原因,它无法处理方法签名字符串的数字元素(可能与内存中的偏移量有关)。 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;
}

答案 1 :(得分: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));
            ...