C#dllimport n#39;跨平台的复杂数据类型?

时间:2014-06-06 19:27:07

标签: c# .net c++-cli native dllimport

所以我在C#中为C dll编写了一个包装器。问题是一些函数使用复杂的数据类型,例如:

ComplexType* CreateComplexType(int a, int b);

有没有办法可以声明一个有效的C#类型,以便我可以使用dllimport? 如果我在做一个仅限Windows的解决方案,我可能会使用C ++ / CLI作为本机复杂类型和托管复杂类型的中间人。

我可以访问C dll的源代码,那么是否可以改为使用opaque类型(例如句柄)?

2 个答案:

答案 0 :(得分:1)

这样的功能很难从C程序中可靠地调用,当你对它进行pinvoke时它并没有变得更好。问题是内存管理,需要再次销毁struct。这要求调用程序使用与完全相同的内存分配器作为DLL。这在C程序中很少见,但您可能很幸运,您拥有DLL的源代码,因此您可以重新编译它并确保每个人都使用相同的共享CRT版本。

当然,C#没有这样的运气,pinvoke marshaller会调用CoTaskMemFree()来释放结构。很少有真正的C程序使用CoTaskMemAlloc()来分配结构,以便在XP上出现静默失败,在Vista及更高版本上出现AccessViolationException。现代Windows版本有一个更严格的堆管理器,它不会忽略无效指针。

您可以将返回值声明为IntPtr,以阻止pinvoke marshaller尝试销毁它。然后手动编组Marshal.PtrToStructure()。这并没有以其他方式阻止内存泄漏,您的程序最终将与OOM崩溃。通常无论如何。

答案 1 :(得分:0)

Mono在Windows与Linux中使用P / Invoke有一个很好的documentation page。具体来说,请参阅编组一节,讨论简单类型和复杂类型。如果您想获得创意,可以将类型序列化为一些方便的基于字符串的格式,如JSON或XML,并将其用作编组机制。