14

我有一个功能:

  myFunction (MyProc callback, void * ref)

这个函数是从一个 Objective-C 类中调用的。该函数被传递一个指向回调(类中的函数)的指针和一个引用。引用是必要的,因为回调是静态调用的,因此没有上下文。ref 可用于为回调提供上下文。

我希望能够通过 Objective-C 类作为参考。所以问题是:

如何将 NSObject 转换为 void * 以及如何将 void * 转换为 NSObject。

提前致谢。

4

3 回答 3

38

做这样的事情:

void func(void *q)
{
    NSObject* o = CFBridgingRelease(q);
    NSLog(@"%@", o);
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSObject* o = [NSObject new];
        func((void*)CFBridgingRetain(o));
    }
    return 0;
}

请注意CFBridgingRetain()CFBridgingRelease()是围绕编译器属性的宏。随意使用。我喜欢 API 变体,因为它在我们的代码库中更常用,而且更明确/更少混淆。

CFBridgingRetain()有效地硬保留必须由 a 平衡的对象CFBridgingRelease()CFTypeRef恰好返回与强制转换兼容的 a void*CFBridgingRelease()有效地撤消了硬保留,因此q只会在有效范围内保持o有效。

void *context;对基本回调有效,但对于必须保留一段时间的类型的东西,你可能不会那样做。为了那个原因:

void callback(void *context)
{
    // grab an ARC aware reference without impacting hard-retain
    NSObject* o = (__bridge NSObject *)(context);
    NSLog(@"%@", o);
}

void freeContext(void *context)
{
    // release the hard-retain
    CFBridgingRelease(context);
}

请注意,如果您省略了 cast / API 调用,Xcode 非常适合准确地建议您应该做什么。它甚至解释了每个替代解决方案的含义(我非常依赖这个,直到我能把它们牢牢记在心里)。

于 2012-10-16T16:36:36.953 回答
8

我假设您正在使用 ARC。你可以在调用时使用这样的东西myFunction

id ref = ...; // your Objective-C object
myFunction(callback, (__bridge_retained void *) ref);

在您的回调中,您必须将所有权转回:

void callback(void* refPtr) {
    id refObj = (__bridge_transfer id) refPtr;
}

根据需要替换id为您的对象类型。

于 2012-10-16T14:23:57.500 回答
1

答:没有办法。void *隐式兼容任何指针类型,所以如果你有一个对象,它是一个类型的指针id(别名为struct objc_object *),你可以简单地将它传递到需要 void 指针的地方,而不需要强制转换。例子:

// this is the declaration of the callback function:
void callback(void *context);

// then you can call it like this:
SomeClass *obj = [[SomeClass alloc] init];
callback(obj);
于 2012-10-16T14:09:22.933 回答