【问题标题】:How do you get data back from C in a C# instantiated array in an C# interop call?如何在 C# 互操作调用中的 C# 实例化数组中从 C 取回数据?
【发布时间】:2011-09-29 18:29:20
【问题描述】:

我想在 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。 IE。 res 值和第一个数组元素一样正确,但不是第二个。因此,布尔数据似乎没有正确编组(除非我遗漏了一些明显的东西)。

我猜也可以声明一个 IntPtr 而不是一个数组,并成功地将这两个元素编组为正确的结果。但是,由于我希望在 C# 中将数组分配到内存中,因此我不确定如何执行此操作。

非常感谢这方面的帮助。我有点卡在这里。 :(


更新:我猜这是因为布尔值只有 1 个字节长,而 C# 代码没有得到这个信息。那么如何指定呢?

【问题讨论】:

    标签: c# c arrays interop boolean


    【解决方案1】:

    使用

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

    应该告诉框架将数组混合为一个 1 字节数组bools。另一种选择是改用 4 字节 BOOL。如需更多信息,请参阅UnmanagedType enum

    【讨论】:

    • 非常感谢!那行得通。我用 ArraySubType = UnmanagedType.Bool 进行了测试,但它不起作用。但我错过了 .NET bool 类型是 4 字节而不是 1。
    • @Tobias,我认为这不是因为 .Net bool 是 4 个字节,而是因为 Win32 BOOL 是 4 个字节。请参阅我链接到的文档。
    • 嗯,布尔类型似乎是一个不同定义的地狱洞,我仍然有(另一个)处理布尔的问题。我会尽快将其作为一个不同的问题发布。从我的阅读来看,.NET Boolean 结构类型似乎是 4 个字节,但回想一下 C# bool 只有 1 个字节的说法。我认为这是错误的,正确映射到布尔结构类型需要 4 个字节。你会同意吗?在我的示例中,我使用了一个 C bool,它显然是 1 个字节,我猜这就是您的响应如此有效的原因。
    • 好吧,bool 的 C# 规范和 System.Boolean 的 MSDN 文档都没有指定大小,因此,理论上,您可以创建一个包含 8 个 bool 字段的结构体和该结构只占用一个字节。在 .Net 的实际实现中,布尔类型本身只占用一个字节,但通常可以填充以更有效地复制到完整的 4 个字节(或 8 个,在 64 位框架上)。见this question
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 2016-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多