2012-04-10 39 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