如何使用P/Invoke将MemoryStream数据传递给非托管C++ DLL

9 c# c++ memorystream parameter-passing

我需要您的帮助,具体情况如下:

我正在从硬件读取一些数据到MemoryStream(C#),我需要将这些数据在内存中传递给在非托管C++中实现的dll(使用指针??).读取的数据(流入)非常大(兆字节).我知道我可以P/Invoke这个dll,但我不确定如何将流数据的指针/引用传递给C++ API?

我必须承认我很困惑,因为我是C#的新手 - 我需要使用unsafe/fixed,因为数据很大或者这些是无关紧要的,因为MemoryStream对象是由GC管理的吗?一些示例代码/详细描述将非常有用.谢谢

非托管API的签名:

BOOL doSomething(void*rawData,int dataLength)

sco*_*ttm 13

如果它只是期望字节,你可以将MemoryStream读入一个字节数组,然后将指针传递给该方法.

你必须声明外部方法:

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

然后,将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();
 }
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的回答。然而,如果你有一个 `MemoryStream`,就没有理由复制数据(`MemoryStream` 只是一个 `byte[]` 的包装器)。相反,您可以使用 [`MemoryStream.GetBuffer()`](https://msdn.microsoft.com/en-us/library/system.io.memorystream.getbuffer (v=vs.110).aspx) 方法。或者我错过了什么? (2认同)