gpt4 book ai didi

c# - P/Invoke [In, Out] 属性对于编码(marshal)处理数组是可选的吗?

转载 作者:可可西里 更新时间:2023-11-01 15:40:12 25 4
gpt4 key购买 nike

假设有一个具有纯 C 接口(interface)的 native 函数,如下所示,从 native DLL 导出:

// NativeDll.cpp

extern "C" void __stdcall FillArray(
int fillValue,
int count,
int* data)
{
// Assume parameters are OK...

// Fill the array
for (int i = 0; i < count; i++)
{
data[i] = fillValue;
}
}

以下 P/Invoke 工作正常(使用 VS2010 SP1 测试):

[DllImport("NativeDll.dll", CallingConvention=CallingConvention.StdCall)]
public static extern void FillArray(
int fillValue,
int count,
[In, Out] int[] data
);

以及此 P/Invoke,与上面相同,但没有 [In, Out] 属性:

[DllImport("NativeDll.dll", CallingConvention=CallingConvention.StdCall)]
public static extern void FillArray(
int fillValue,
int count,
int[] data
);

那么,那些 [In, Out] 属性是用于编码(marshal)处理数组的可选吗?如果有的话,他们的目的是什么?可以在我们的 P/Invoke 声明中省略它们吗?

最佳答案

不,它们完全不是可选的。它只是偶然地工作。然而,这是一个非常常见的事故。它之所以有效,是因为数组实际上并没有被编码。 pinvoke 编码器看到 C# 数组已经与 native 数组兼容,因此跳过创建它的拷贝的步骤。它只是固定数组并将指针传递给 native 代码。

这当然是非常高效的,您将不可避免地得到返回结果,因为 native 代码是直接写入数组元素。因此 [In] 和 [Out] 属性都不重要。

如果数组元素类型不是那么简单,它就会变得更加模糊。识别不可 blittable 或编码后布局不匹配的结构或类类型的元素类型并不容易,因此 pinvoke 编码器必须制作数组的拷贝.尤其是布局不兼容可能非常难以识别,因为托管布局是不可发现的。并且可以根据使用的抖动而改变。 It may work in x86 but not x64 for example, pretty nasty when AnyCPU is selected.让它将修改后的拷贝复制回 C# 数组确实需要[Out]。

不知道该建议什么,除了没有人因为在声明中明确表达而被解雇。当数组元素类型不简单时,也许您应该始终明确,这样您就永远不会发生意外。

关于c# - P/Invoke [In, Out] 属性对于编码(marshal)处理数组是可选的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14366066/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com