保留C库调用中的.NET对象的C ++ / CLI句柄

时间:2012-04-10 15:59:46

标签: c# c c++-cli clr

我有一个C#库,需要用作直接的C Win32应用程序的一部分。我试图在C++ / CLI中编写一个可以处理C#.NET对象的包装器。唯一的问题是整个项目不能用C ++编译,它必须留在C.

为了解决这个问题,我想不透明地将我的C#对象的实例传递回C代码,这样它们就可以传入并在包装库调用中使用,但我无法弄清楚如何去做。例如,我想做这样的事情:

C ++ / CLI Wrapper:

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库调用中再次使用。

有什么建议吗?

1 个答案:

答案 0 :(得分:3)

你无法将句柄存储在void *中,因为垃圾收集器可以移动对象,使指针变得比无用的更糟糕(它现在会指向其他一些随机对象)。

您需要使用C ++ / CLI提供的gcroot模板。然后,您可以将gcroot<MyObject>*存储到void*并将其传递给您的C代码。当你完成它时,不要忘记正确地释放gcroot,以便运行析构函数。

您还可以查看GCHandle类,它是.NET类库的一部分。但是在C ++ / CLI代码中建议使用gcroot(它在内部使用GCHandle