混合C和Objective-C时的ivars

时间:2010-10-24 18:39:27

标签: objective-c c cocoa

我正在为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是否相同? (毕竟,它没有被声明为实例变量......)

2 个答案:

答案 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”参数传递来利用此功能。

然后在回调中,将指针强制转换回对象并进行所需的调用。