Как я могу передать данные MemoryStream в неуправляемую C ++ DLL с помощью P / Invoke - PullRequest
9 голосов
/ 28 июня 2009

Мне нужна ваша помощь по следующему сценарию:

Я читаю некоторые данные с аппаратного обеспечения в MemoryStream (C #), и мне нужно передать эти данные в памяти в dll, реализованную в неуправляемом C ++ (с использованием указателя ??). Считываемые данные (в поток) очень большие (мегабайты). Я понимаю, что я могу P / Invoke этой DLL, но я не уверен, как передать указатель / ссылку на данные потока в API C ++?

Должен признать, что я смущен, поскольку я новичок в C # - нужно ли использовать небезопасные / фиксированные данные, поскольку объем данных велик или они не имеют значения, поскольку объект MemoryStream управляется GC? Некоторый пример кода / подробное описание было бы очень полезно. Спасибо

Подпись неуправляемого API:

BOOL doSomething (void * rawData, int dataLength)

1 Ответ

13 голосов
/ 28 июня 2009

Если он ожидает байты, вы можете прочитать MemoryStream в байтовый массив и затем передать указатель на метод.

Вы должны объявить внешний метод:

[DllImport("mylibrary.dll", CharSet = CharSet.Auto)]
public static extern bool doSomething(IntPtr rawData, int dataLength);

Затем считайте байты из MemoryStream в байтовый массив. Выделите GCHandle , который:

После выделения вы можете использовать GCHandle предотвратить управляемый объект от собирать мусор Коллектор, когда неуправляемый клиент содержит единственную ссылку. Без таких ручка, предмет можно собрать сборщиком мусора перед завершение своей работы от имени неуправляемый клиент.

И, наконец, используйте метод AddrOfPinnedObject, чтобы получить IntPtr для передачи в C ++ dll.

private void CallTheMethod(MemoryStream memStream)
{
   byte[] rawData = new byte[memStream.Length];
   memStream.Read(rawData, 0, memStream.Length);

   GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
   IntPtr address = handle.AddrOfPinnedObject ();

   doSomething(address, rawData.Length);
   rawDataHandle.Free();
 }
...