将数据从非托管代码(C)传递到托管代码(C#)
我有一个在C#
中编写的应用程序,它使用编写在C
中的DLL。 通过一些委托(函数指针),我设法调用了一个C
函数。预计此功能会对某些数据执行大量处理,然后将处理后的二进制数据连同数据大小一起返回到C#
代码。将数据从非托管代码(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);
顺便说INT这种情况下foo()
不需要采取cs_size
参数,因为它可以使用数组的.Length
属性。
这个
此外,由于C#代码复制数组,你可以只调用回调后free()
从C代码的缓冲区。
否则你需要或者从C导出mylib_free()
方法或使用已知的内存分配器(NOT malloc
)像LocalAlloc
(从C)和Windows下Marshal.FreeHGlobal
(从C#)。
这是Microsoft为C++/CLI制作的(也称为托管C++)。你可以写这样的功能:
void call_foo(array<Byte>^ bytes)
{
pin_ptr<Byte> ptrBuffer = &bytes[bytes->GetLowerBound(0)];
foo(ptrBuffer, bytes->Length);
}
这将需要字节的C#阵列,其引脚内存,然后把它作为字节FOO的一个C风格的数组,它的长度。没有必要清理或释放任何东西。固定指针在call_foo结束时超出范围时将自动取消固定。清洁和简单。
如果您的项目中没有托管的C++代码,并且只是这一个调用,那么这是最佳解决方案。 –
+1。这工作。谢谢 :)。但是,我只是在想,这不会引入额外的复制开销吗? –
它的确如此,但它仍然是最好的解决方案,如果您没有任何托管C++并且您没有太多这样的调用,并且性能不是很重要。我的答案可以用来避免额外的副本,但是你必须创建一个C++项目(可以编译成一个点网络程序集)。 –