- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
假设有一个具有纯 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/
我是一名优秀的程序员,十分优秀!