[英]How to map and marshal a C array into a C# code
我正在编写调用C库的C#代码,这在我看来并不是很清楚。
C函数有这个签名:
double* DoSomeStuff(double* input,int numberOfElements);
我已将函数映射为:
[System.Runtime.InteropServices.DllImportAttribute("myDll.dll", EntryPoint="DoSomeStuff")]
public static extern System.IntPtr DoSomeStuff(ref double input, int numberOfElements) ;
输入值是一个数组,因此C函数将期望连续的内存布局。 我比C#更熟悉C ++。 在C ++中,我使用std :: vector来存储数据,然后我将使用data()方法获取指针并使用C代码交换信息。 std :: vector保证了连续的布局内存。
我可以在C#中使用哪种数据结构? 在C#中有什么类似std :: vector的东西吗?
我面临着一个字符串的相同问题(在C ++中,std :: string只是一个带有一些化妆的std :: vector)。 我用以下方法解决了这个问题:
System.IntPtr stringExample = Marshal.StringToHGlobalAnsi("StringExample");
静态功能为我完成了这项工作。 其他类型有什么类似的功能吗?
我已经问了太多问题,我认为最重要的问题是:解决这类问题的最佳做法是什么?
谢谢
将输入定义为IntPtr:
[System.Runtime.InteropServices.DllImportAttribute("myDll.dll", EntryPoint="DoSomeStuff")]
public static extern System.IntPtr DoSomeStuff(IntPtr input, int numberOfElements) ;
在固定块中创建一个数组,然后从指针创建一个IntPtr,然后将其传递给DoSomeStuff
。
double[] input = new double[20];
IntPtr result = IntPtr.Zero;
fixed(double* d = &input[0])
{
result = DoSomeStuff(new InptPtr(d), 20);
}
...
fixed
块的原因是,当非托管代码填充时,GC不会移动阵列。
为了使您的示例工作,您应该定义extern函数的siganture,如下所示:
[System.Runtime.InteropServices.DllImportAttribute("myDll.dll", EntryPoint="DoSomeStuff")]
public static extern System.IntPtr DoSomeStuff([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)], int numberOfElements);
MarshalAs attaribute的第二个(命名)参数告诉编组器存储数组大小的位置。
关于第二个问题,C#有List<Type>
类,其行为类似于std:vector<Type>
。 但是,我不认为你可以直接提供给编组人员。 你可以做的是使用List
类的ToArray()
方法来获得一个数组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.