我有一个功能:
myFunction (MyProc callback, void * ref)
这个函数是从一个 Objective-C 类中调用的。该函数被传递一个指向回调(类中的函数)的指针和一个引用。引用是必要的,因为回调是静态调用的,因此没有上下文。ref 可用于为回调提供上下文。
我希望能够通过 Objective-C 类作为参考。所以问题是:
如何将 NSObject 转换为 void * 以及如何将 void * 转换为 NSObject。
提前致谢。
我有一个功能:
myFunction (MyProc callback, void * ref)
这个函数是从一个 Objective-C 类中调用的。该函数被传递一个指向回调(类中的函数)的指针和一个引用。引用是必要的,因为回调是静态调用的,因此没有上下文。ref 可用于为回调提供上下文。
我希望能够通过 Objective-C 类作为参考。所以问题是:
如何将 NSObject 转换为 void * 以及如何将 void * 转换为 NSObject。
提前致谢。
做这样的事情:
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 非常适合准确地建议您应该做什么。它甚至解释了每个替代解决方案的含义(我非常依赖这个,直到我能把它们牢牢记在心里)。
我假设您正在使用 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
为您的对象类型。
答:没有办法。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);