c# P/Invoke [DllImport] -数组内存管理

本文关键字:数组 内存 管理 DllImport Invoke | 更新日期: 2023-09-27 18:01:49

我将一个byte[]传递给一个接受unsigned char*的函数

我可以这样做的一种方法是传递一个IntPtr,并在托管代码中分配/释放内存,如下所示:
    c++ DLL中的
  • extern "C" 
    {
        __declspec(dllexport) void __stdcall Foo(int length, unsigned char** message);
    }
    

  • 用c#
  • [DllImport(@"MyDll.dll"]
    public static extern void Foo(int length, ref IntPtr msg);
    byte[] msg = new byte[] {0,1,2,3};
    IntPtr ip = Marshal.AllocHGlobal(msg.Length);
    Marshal.Copy(msg, 0, ip, msg.Length);
    UnmanagedCode.Foo(msg.Length, ref ip);
    Marshal.FreeHGlobal(ip);
    

我也可以这样做:

    c++ DLL中的
  • extern "C" 
    {
        __declspec(dllexport) void __stdcall Foo(int length, unsigned char* message);
    }
    

  • 用c#
  • [DllImport(@"MyDll.dll"]
    public static extern void Foo(int length, byte[] msg);
    byte[] msg = new byte[] {0,1,2,3};
    UnmanagedCode.Foo(msg.Length, msg);
    

两种实现都工作得很好,但在我的第二个例子中,如何管理内存(用于unsigned char*消息)。我猜内存是在调用Foo时分配的,当它返回时释放(所以它的行为很像第一个例子)-这是正确的吗?

谢谢

c# P/Invoke [DllImport] -数组内存管理

在第二种情况下没有进行管理。GC不计算来自非托管代码的引用。当外部函数不与线程一起工作或在以后的函数调用中使用引用时,这是可以的。
有一个类似的问题,当你与委托/函数指针和非托管代码工作,它可能发生在你的委托在一个随机点被释放。这篇MSDN文章很好地解释了所有的细节。