繁体   English   中英

如何将C数组映射和编组为C#代码

[英]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"); 

静态功能为我完成了这项工作。 其他类型有什么类似的功能吗?

我已经问了太多问题,我认为最重要的问题是:解决这类问题的最佳做法是什么?

谢谢

1)

将输入定义为IntPtr:

[System.Runtime.InteropServices.DllImportAttribute("myDll.dll", EntryPoint="DoSomeStuff")]
public static extern  System.IntPtr DoSomeStuff(IntPtr input, int numberOfElements) ;

2)

固定块中创建一个数组,然后从指针创建一个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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM