将数据从非托管代码(C)传递到托管代码(C#)

我有一个用C#编写的应用程序,并使用一个用C编写的DLL。 通过一些委托(函数指针),我设法调用了一个C函数。 期望该函数对某些数据进行大量处理,然后将处理后的二进制数据与数据大小一起返回给C#代码。

托管c#函数的原型是:

private unsafe delegate void MyCallback (IntPtr cs_buf, Int32 cs_size);

我从我的C code调用它为:

 void* c_buf = NULL; int c_size = 0; .... some processing here to fill buf and size...... MyCallback (c_buf, c_size); 

在托管的C#代码中,我需要调用具有原型的MyCallback函数:

void foo (byte[] cs_buf, int cs_size)

现在cs_size值没有问题,但是使用/将二进制缓冲区从C代码传递给C#代码的正确方法是什么,这样它就可以用作C#代码中的byte[]

如果我正在做的是正确的方法,那么将接收到的IntPtr cs_buf转换为byte[]的推荐方法应该是什么?

谢谢,维克拉姆

你应该使用Marshal.Copy

Marshal.Copy Method (IntPtr, Byte[], Int32, Int32)

将数据从非托管内存指针复制到托管8位无符号整数数组。

假设cs_size是以字节为单位的大小:

 var array = new byte[cs_size]; Marshal.Copy(pointer, array, 0, cs_size); foo(array, cs_size); 

顺便说一下,在这种情况下, foo()不需要采用cs_size参数,因为它可以使用数组的cs_size属性。


另外,当C#代码复制数组时,您可以在调用回调后立即从C代码中free()缓冲区。

否则,您需要从C导出mylib_free()方法,或者在Windows下使用已知的内存分配器(NOT malloc ),如LocalAlloc (From C)和Marshal.FreeHGlobal (From C#)。

这就是Microsoft制作C ++ / CLI(也称为托管C ++)的原因。 你可以写一个这样的函数:

 void call_foo(array^ bytes) { pin_ptr ptrBuffer = &bytes[bytes->GetLowerBound(0)]; foo(ptrBuffer, bytes->Length); } 

这将采用C#字节数组,固定其内存,然后将其作为C样式字节数组传递给foo及其长度。 无需清理或释放任何东西。 固定指针在call_foo结束时超出范围时将自动取消固定。 干净简单。