C # P / Invoke [DllImport] - управление памятью массива - PullRequest
3 голосов
/ 11 июля 2011

Я передаю байт [] в функцию, принимающую беззнаковый символ *

Один из способов сделать это - передать 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);
    

Обе реализацииработают хорошо, но во втором примере, как управляется память (для неподписанного сообщения char *).Я предполагаю, что память выделяется, когда выполняется вызов Foo, и освобождается, когда он возвращается (поэтому он ведет себя так же, как в первом примере) - это правильно?

Спасибо

1 Ответ

2 голосов
/ 11 июля 2011

Во втором случае управление не выполняется. GC не считает ссылки, сделанные из неуправляемого кода. Это нормально, когда внешняя функция не работает с потоками или использует ссылку при более позднем вызове функции.
Существует аналогичная проблема, когда вы работаете с делегатами / указателями на функции и неуправляемым кодом, где с вами может случиться делегат освобождается в случайном порядке. Эта статья MSDN замечательно объясняет вам все детали.

...