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

Til*_*ütz 6 objective-c objective-c-runtime

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

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

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

[更新]

我无法使用Apple Foundation.

Jos*_*ell 5

我相信你正在寻找NSGetSizeAndAlignment:

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

const char * NSGetSizeAndAlignment (
   const char *typePtr,
   NSUInteger *sizep,
   NSUInteger *alignp
);
Run Code Online (Sandbox Code Playgroud)

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

这是一个Foundation函数,不是基本运行时的一部分,这可能是您找不到它的原因.

更新:虽然你最初没有提到你正在使用Cocotron,但它也可以在那里使用.你可以找到它在Cocotron的基础上,在 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;
}
Run Code Online (Sandbox Code Playgroud)


jus*_*tin 2

据我所知,您需要将该信息烘焙到您的二进制文件中。只需创建一个函数,该函数返回结构中的 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;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用它作为起点:

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));
            ...
Run Code Online (Sandbox Code Playgroud)