将数据从非托管代码(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结束时超出范围时将自动取消固定。 干净简单。