C#P / Invoke [DllImport] - 阵列内存管理

时间:2011-07-11 14:34:41

标签: c# arrays memory-management pinvoke dllimport

我将一个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时会分配内存,并在返回时释放内存(因此它的行为与第一个示例非常相似) - 这是正确的吗?

由于

1 个答案:

答案 0 :(得分:2)

第二种情况没有管理。 GC不计算从非托管代码完成的引用。当外部函数不能与线程一起使用或在以后的函数调用中使用引用时,这很好。
当你使用委托/函数指针和非托管代码时会出现类似的问题,它可能发生在你身上代表在随机点获得交易。 这个MSDN article非常适合向您解释所有细节。