2012-04-10 36 views
1

我有一個C#庫需要用作直C Win32應用程序的一部分。我正在嘗試編寫一個可以處理C#.NET對象的包裝函數C++/CLI。唯一的問題是,整個項目不能用C++編譯,它必須留在C.在C庫調用中保留C++/CLI句柄以處理.NET對象

要解決這個問題,我想不透明地將C#對象的實例傳遞迴C代碼,以便它們可以傳入並用於包裝庫調用,但我無法弄清楚如何做到這一點。舉例來說,我願做這樣的事情:

C++/CLI包裝:

void * ReturnObject(char *name){ 
    return (void *)gcnew MyObject(gcnew String(name)); 
} 

void UseObject (void *object){ 
    MyObject ^handle = (MyObject ^)object; 
    object -> use(); 
} 

使用C++靜態庫原生的C代碼:

int main (char **argv){ 
    void *obj = ReturnObject("foobar"); 
    UseObject(obj); 
} 

所以C代碼沒有按」不要在意obj的內容是什麼,甚至不知道CLR類型MyObject,但它只是繞過數據來維護對象持久性。我想這應該用void指針來完成,但C++編譯器不想執行這些轉換。我不知道是否由於託管內存和非託管內存之間的差異,或者如果我沒有正確執行,但我當然會很感激任何幫助。

因此,回顧一下: 我想在C++/CLI包裝庫中實例化.net對象,並將這些對象保存在直接C代碼中,以便可以在其他C++/CLI庫調用中再次使用它們尚未寫入。

有什麼建議嗎?

回答

3

您不能將句柄存儲在void *中,因爲垃圾收集器可以移動對象,使指針變得比無用(它現在指向其他一些隨機對象)變得更糟。

您需要使用由C++/CLI提供的gcroot模板。然後,您可以將gcroot<MyObject>*存儲到void*中,並將其傳遞給您的C代碼。當你完成它時,不要忘記正確地釋放gcroot,以這樣的方式運行析構函數。

您還可以查看GCHandle類,它是.NET類庫的一部分。但推薦在C++/CLI代碼中使用gcroot(它在內部使用GCHandle)。

+0

好吧,所以我想我已經得到了這個,但現在我無法弄清楚如何調用對象的方法。這裏是我的: 'gcroot * handle =(gcroot *)object;' 其中'object'作爲void指針傳入。 如何訪問對象的方法和成員?當我嘗試使用常規句柄來處理someMethod()時,編譯器只是說someMethod不是gcroot 的成員。 – Drewmate 2012-04-10 17:13:32

+1

@Drewmate:你需要'(* handle) - > someMethod()'。 – 2012-04-10 17:23:24