PInvoke:在C ++中分配内存并在C#中释放它 [英] PInvoke: Allocate memory in C++ and free it in C#

查看:88
本文介绍了PInvoke:在C ++中分配内存并在C#中释放它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在使用PInvoke在C#和C ++之间互操作.

We are using PInvoke to interop between C# and C++.

我有一个互操作结构,如下,另一侧具有相同的布局C ++结构.

I have an interop struct as follows, with an identical layout C++ struct on the other side.

[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

Now I would like to add a second ctor

    public MeshDataStruct(bool filled_in_by_native_codee)
    {
        _vertex_count = 0;
        _vertices = IntPtr.Zero;
    }

,然后用C ++编写一个方法,该方法允许C ++填充数据.这将使我们能够对输入和输出数据使用相同的结构...

and then write a method in C++ that allows C++ to fill in the data. This would allow us to use the same structure for input as well as output data...

但是,据我了解,AllocHGlobal在C#和C ++/Cli中可用,但不是纯C ++.

However, as far as I understand it, AllocHGlobal is available in C# and C++/Cli, but not pure C++.

所以我的问题是:如何在C ++中分配内存,以便可以通过调用Marshal.FreeHGlobal(...)在C#端安全地释放它?

So my question is: How can I allocate memory in C++ such that I can safely free it on the C# side with a call to Marshal.FreeHGlobal(...)?

推荐答案

按照传统,这种方法总是效果很差,Microsoft CRT使用HeapCreate()创建了自己的堆来为C或C ++程序中的malloc/new调用提供服务.无法在C#中释放这样的内存,您没有堆句柄.

This traditionally always ended up poorly, the Microsoft CRT created its own heap with HeapCreate() to service malloc/new calls in a C or C++ program. Can't deallocate such memory in C#, you don't have the heap handle.

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

That has changed however, starting with the CRT included with VS2012 (msvcr120.dll and up). It now uses the default process heap, the one returned by GetProcessHeap(). Also the one used by Marshal.Alloc/FreeHGlobal(). So you now have a shot at it, provided the native code doesn't use the debug allocator (crtdbg.h). Be careful throwing away that debug option.

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

The pinvoke marshaller was not changed, nor can it. If it has to release memory, like an array or string returned as a function return value, then it will call CoTaskMemFree(). It is not clear from your question which could apply. In case of doubt and if you have the choice in your native code then you can't go wrong with CoTaskMemAlloc(), paired to Marshal.FreeCoTaskMem() in your C# code.

这篇关于PInvoke:在C ++中分配内存并在C#中释放它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆