gpt4 book ai didi

c# - PInvoke:在 C++ 中分配内存并在 C# 中释放它

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:27:49 27 4
gpt4 key购买 nike

我们正在使用 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++ 中分配内存,以便我可以通过调用 Marshal.FreeHGlobal(...) 在 C# 端安全地释放它?

最佳答案

传统上这总是以糟糕的方式结束,Microsoft CRT 使用 HeapCreate() 创建了自己的堆来为 C 或 C++ 程序中的 malloc/new 调用提供服务。无法在 C# 中释放此类内存,因为您没有堆句柄。

但是,从 VS2012 中包含的 CRT(msvcr120.dll 及更高版本)开始,情况发生了变化。它现在使用默认进程堆,即 GetProcessHeap() 返回的进程堆。也是 Marshal.Alloc/FreeHGlobal() 使用的那个。现在您可以尝试一下了,前提是 native 代码不使用调试分配器 (crtdbg.h)。小心丢弃该调试选项。

pinvoke 编码器未更改,也不能更改。如果它必须释放内存,比如作为函数返回值返回的数组或字符串,那么它将调用 CoTaskMemFree()。从您的问题中不清楚哪个可以适用。如有疑问,并且如果您在 native 代码中有选择,那么 CoTaskMemAlloc() 不会出错,它与 C# 代码中的 Marshal.FreeCoTaskMem() 配对。

关于c# - PInvoke:在 C++ 中分配内存并在 C# 中释放它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33481888/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com