tha*_*alm 7 c c# arrays marshalling
我想将float []传递给C方法.C签名如下:
EXTERN int process_raw(float *inBuffer, float *outBuffer);
Run Code Online (Sandbox Code Playgroud)
在C#中,签名是:
public static extern int process_raw(ref float inBuffer, ref float outBuffer);
Run Code Online (Sandbox Code Playgroud)
将带有ref的数组传递给第一个成员会有问题吗:
process_raw(ref someArray[0], ref anotherArray[0])
Run Code Online (Sandbox Code Playgroud)
谢谢!
编辑:当然重要的是要知道C代码对浮点数的作用:它将它们视为数组,并将从inBuffer读取值并将值写入outBuffer.如下所述,问题是在PInvoke调用期间是否会固定整个内存?
编辑2:另一个评论.我故意选择ref float因为我也想做以下事情:
fixed(byte* outBuff = buffer)
{
Process(ticks, ref aFloat, ref ((float*)outBuff)[0]);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下它应该没有问题,因为指针仍然是固定的,但上面的正常数组的问题仍然存在.
p/Invoke 中不涉及自动固定。P/Invoke 严格通过编组执行!(没有不安全代码)编组意味着分配(非托管)内存和复制。在幕后,可能在复制期间有一个引脚,但在本机函数调用期间没有。
如果您需要将 64 个浮点数的数组传入和传出本机函数,您有两种选择:
这是编组方法:
[DllImport(...)]
private extern static int process_raw([In] float[] inBuffer, [Out] float[] outBuffer);
Run Code Online (Sandbox Code Playgroud)
请注意,我添加了 [In] 和 [Out] 属性,因为它们告诉编组器 (In) 不要在出路时进行复制,而 (Out) 不要在入路时进行复制。 最好在以下情况下始终考虑这些属性:编写 ap/invoke 声明。
这是不安全的方法:
[DllImport(...)]
private extern static unsafe int process_raw(float * inBuffer, float * outbuffer);
public static unsafe int Process(float[] inBuffer, float[] outBuffer)
{
// validate for null and Length < 64
fixed (float * pin = inBuffer)
fixed (float * pout = outBuffer)
return process_raw(pin, pout);
}
Run Code Online (Sandbox Code Playgroud)
扩展评论
据我了解,编组器能够“在某些情况下”选择固定托管内存,而不是分配非托管内存和复制。问题是:什么情况下?
我不知道答案,但我有一个怀疑:当本机DLL是某些系统DLL时。这只是一个猜测。
这对你我来说意味着非常简单:始终从编组方法开始。如果您遇到性能问题,并且分析器告诉您本机调用消耗了大量时间,那么您可以尝试不安全的方法并再次分析它。如果没有显着的改进,那么您唯一的希望就是优化本机调用。