我们正在使用PInvoke在C#和C ++之间互操作。
我有一个互操作结构,如下所示,另一侧具有相同的布局C ++结构。
[StructLayout(LayoutKind.Sequential)]
public struct MeshDataStruct : IDisposable
{
public MeshDataStruct(double[] vertices, int[] triangles , int[] surfaces)
{
_vertex_count = vertices.Length / 3;
_vertices = Marshal.AllocHGlobal(_vertex_count*3*sizeof (double));
Marshal.Copy(vertices, 0, _vertices, _vertex_count);
}
// .. extract data methods to double[] etc.
private IntPtr _vertices;
private int _vertex_count;
public void Dispose()
{
if (_vertices != IntPtr.Zero)
{
Marshal.FreeHGlobal(_vertices);
_vertices = IntPtr.Zero;
}
}
}
现在我想添加第二个ctor
public MeshDataStruct(bool filled_in_by_native_codee)
{
_vertex_count = 0;
_vertices = IntPtr.Zero;
}
然后用C ++编写一个方法,该方法允许C ++填充数据。这将使我们能够对输入和输出数据使用相同的结构...
但是,据我了解,它AllocHGlobal
可以在C#和C ++ / Cli中使用,但不能用于纯C ++。
所以我的问题是:如何在C ++中分配内存,以便可以通过调用C#来安全地释放它Marshal.FreeHGlobal(...)
?
传统上,这种方法通常效果很差,Microsoft CRT使用HeapCreate()创建了自己的堆,以便为C或C ++程序中的malloc / new调用提供服务。无法在C#中释放此类内存,因为您没有堆句柄。
但是,这已经发生了变化,从VS2012附带的CRT(msvcr120.dll及更高版本)开始。现在,它使用默认的进程堆,即GetProcessHeap()返回的堆。也是Marshal.Alloc / FreeHGlobal()使用的那个。因此,如果本机代码不使用调试分配器(crtdbg.h),那么现在您可以尝试一下。请小心丢弃该调试选项。
Pinvoke编组器没有更改,也没有更改。如果它必须释放内存,例如作为函数返回值返回的数组或字符串,则它将调用CoTaskMemFree()。从您的问题尚不清楚哪个适用。如有疑问,并且如果您可以在本机代码中进行选择,那么CoTaskMemAlloc()不会出错,它在C#代码中与Marshal.FreeCoTaskMem()配对。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句