2010-10-24 181 views
0

我正在爲C庫編寫一個Objective-C包裝,並且在訪問我的ivars的引用時遇到問題。ivars當混合C和Objective-C

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函數調用)。從計算器舊的問題提出來定義在頭文件中的附加變量(例如theDelegate):

 
id theDelegate; 

@interface Controller : NSObject { 
    id delegate; 
} 
@property (assign) id delegate; 
@end 

然後,每當我的delegate值更改爲一個新的,我有這個值賦給theDelegate,太。

由於我的C是有點生疏了,這裏是我的問題:

1)我可以將指針傳遞RegisterClient C函數的Objective-C的方法,而不是指向一個函數作爲參數,以完全避免C函數handleEvent

2)如果不是的話:當我創建這個Objective-C類的多個實例時,theDelegate對所有實例都是一樣的嗎? (畢竟,它沒有被聲明爲一個實例變量......)

+1

void * Event參數 - 它是什麼?如果它是作爲上下文參數傳遞的東西,則可以傳遞委託。 – 2010-10-24 20:51:46

+0

void * Event參數包含有關事件的詳細信息。但是你做了一個有用的評論:'int handleEvent(void * Event)'實際上是'int handleEvent(void * Event,void * Cookie)'。當開始搜索時,我可以傳遞任何我想作爲「cookie」的東西,如果發生事件,它將出現在handleEvent函數中。非常感謝! – pruefsumme 2010-10-25 07:37:23

回答

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

大多數像一個你描述接受「用戶信息」參數方便的大小,以匹配指針的時間C庫。你可以通過傳遞你的對象作爲這個「userinfo」參數來使用它。

然後在回調中,您將指針轉回到一個對象並進行所需的調用。