将 Objective-C 对象作为 void * 指针传递给函数 [英] Pass an Objective-C object to a function as a void * pointer

查看:24
本文介绍了将 Objective-C 对象作为 void * 指针传递给函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个功能:

  myFunction (MyProc callback, void * ref)

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

This function is called from within an Objective-C class. The function is passed a pointer to the callback (a function in the class) and a reference. The reference is necessary because the callback is called statically and therefore doesn't have a context. The ref can be used to provide a context to the callback.

我希望能够将 Objective-C 类作为参考传递.所以问题是:

I want to be able to pass the Objective-C class as the reference. So the question is:

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

How do I cast an NSObject to a void * and how do I cast a void * as an 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 变体,因为它在我们的代码库中更常用,而且更明确/更少混淆.

Note that CFBridgingRetain() and CFBridgingRelease() are macros around compiler attributes. Feel free to use either. I like the API variant as it is in more common use in our codebases and it is more explicitly / less confusing.

CFBridgingRetain() 有效地硬保留必须由 CFBridgingRelease() 平衡的对象.它也碰巧返回一个 CFTypeRef,它与 void* 的转换兼容.CFBridgingRelease() 有效地取消了硬保留,因此 q 只会在 o 有效的范围内保持有效.

CFBridgingRetain() effectively hard-retains the object that must be balanced by a CFBridgingRelease(). It also happens to return a CFTypeRef which is compatible with a cast to void*. CFBridgingRelease() effectively undoes that hard-retain and, thus, q will only remain valid within the scope that o is valid.

对于基本回调有效,但您可能不会使用 void *context; 类型的东西,它必须坚持一段时间.为此:

Valid for basic callbacks, but you'd probably not what that with a void *context; type thing that has to stick around for a while. For that:

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

请注意,如果您省略了演员表/API 调用,Xcode 非常擅长准确地建议您应该做什么.它甚至解释了每个替代解决方案的含义(我非常依赖这个,直到我能把它们放在我的脑海里).

Note that Xcode is quite good about suggesting exactly what you should do if you leave out the cast / API call. It even explains the meanings of each of the alternative solutions (I relied on this heavily until I could keep 'em straight in my head).

这篇关于将 Objective-C 对象作为 void * 指针传递给函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆