如何在c#互操作调用中以c#实例化数组的形式从C中获取数据?

本文关键字:获取 数据 实例化 互操作 调用 数组 | 更新日期: 2023-09-27 18:01:15

我想在c#中实例化布尔数组的内存,并使用互操作将其传递给C库函数。然后,C函数应该用数据(结果)填充数组,以便将数据传递回c#并在那里使用。由于数组是引用类型,并且我显式地为数组设置了[In, Out]编组属性,因此我认为这将是小菜一碟。但显然不是。下面是一些说明问题的测试代码(尽可能简单)。

在C语言中,我称之为:

extern "C" __declspec(dllexport) int __stdcall TestFillArray(bool *resultMaterials, int materialLength);

__declspec(dllexport) int __stdcall TestFillArray(bool *resultMaterials, int materialLength)
{
    resultMaterials[0] = true; 
    resultMaterials[1] = true; 
    return materialLength;
}

我用下面的声明从c#调用这个函数:

[DllImport("FrontAuction2.dll", CharSet = CharSet.Auto, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public static extern int TestFillArray([MarshalAs(UnmanagedType.LPArray, SizeConst = 2), In, Out] bool[] resultMaterial, int materialLength);

然后在我的c#测试方法中,我有:

var resultMaterials = new bool[2];
var res = TestFillArray(resultMaterials, 2);

当我检查结果时,我得到res=2和resultMaterials[0] = true,和resultMaterials[1] = false。也就是说,res值和第一个数组元素一样正确,但第二个不是。因此,布尔数据似乎没有正确编组(除非我错过了一些明显的东西)。

我猜也可以声明一个IntPtr而不是一个数组,并成功地将两个元素封送到正确的结果。然而,由于我希望数组在c#中分配内存,我不确定如何做到这一点。

非常感谢你在这件事上的帮助。我被困在这里了。(

UPDATE:我猜这是由于布尔值只有1字节长,c#代码没有得到这个信息。那么如何指定这个呢?

如何在c#互操作调用中以c#实例化数组的形式从C中获取数据?

使用

[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1, SizeConst = 2), In, Out]

应该告诉框架将数组作为一个1字节的bool数组进行mashal。另一种选择是使用4字节的BOOL。详细信息请参见UnmanagedType enum