我正在为C库编写一个Objective-C包装器,并且在访问我的ivars的引用时遇到了问题。
C库要求我指定一个处理事件的函数指针,我在Objective-C类的初始化期间指定它。
- (id) init { [super init]; RegisterClient(&handleEvent); return self; }
C库能够开始搜索某些内容,然后在搜索过程中发生任何事情时调用handleEvent函数。该功能(基本上)看起来像这样。
int handleEvent(void *Event) { [delegate didFinishSearching]; return 0; }
至少我希望它看起来像这样。问题是代码不会构建因为'delegate' undeclared (first use in function)
(当然我已经声明了,我可以从任何Objective-C方法调用[delegate didFinishSearching]
而不是从C函数调用)。 stackoverflow中的旧问题建议在头文件中定义一个额外的变量(例如theDelegate
):
id theDelegate; @interface Controller : NSObject { id delegate; } @property (assign) id delegate; @end
然后,每当我将delegate
的值更改为新值时,我都必须将此值分配给theDelegate
。
由于我的C有些生疏,以下是我的问题:
1)我可以将RegisterClient
C函数传递给Objective-C方法而不是指向函数的指针作为参数,以便完全避免C函数handleEvent
吗? p>
2)如果不是:当我创建此Objective-C类的多个实例时,所有实例的theDelegate
是否相同? (毕竟,它没有被声明为实例变量......)
答案 0 :(得分:3)
Objective-C方法是C函数,但它们在前面有两个隐藏参数,因此它们没有int f(void *)
签名。
您可能想要做的是使用libffi闭包。这允许您创建一个具有您想要的完全签名的函数,但是它也有一个指向您传递的对象的指针。请参阅ffi_prep_closure
man page中的示例。您的handleEvent
函数可能会改为看起来像这样:
static void handleEventClosure(ffi_cif * cif, void * result, void ** args, void * userdata)
{
// Arguments.
void * Event = *args[0];
// Closed-over data.
id delegate = (id)userdata;
// Execute the method.
[delegate didFinishSearching];
// Smaller than sizeof(long), so use ffi_arg or ffi_sarg (unsigned or signed).
*(ffi_sarg *)result = (ffi_sarg)0;
}
答案 1 :(得分:2)
大多数时候,像你描述的那样的C库接受一个“userinfo”参数,方便地调整大小以匹配指针。您可以通过将对象作为此“userinfo”参数传递来利用此功能。
然后在回调中,将指针强制转换回对象并进行所需的调用。