我知道第一组关键字in, out, ref
可以在所有C#函数中使用,第二组属性[In], [Out], [In, Out]
用于编组。
我不确定在本机代码的函数声明中使用它们时是否表示同一意思。例如,以下两个声明是否等效?
[DllImport("xxx.dll")]
void FillArray1(ref int[] arr, in int length);
[DllImport("xxx.dll")]
void FillArray2([In, Out] int[] arr, [In] int length);
是否有两组不相等的情况?
答案 0 :(得分:1)
它们不是等效的。
对于ref int[] arr
,默认的[In, Out]
属性将自动应用,但仍与[In, Out] int[] arr
不同。
ref int[] arr
是双重间接寻址(通过引用传递的引用类型)。如果本机端定义如下:int32_t** arr
,请使用此选项。这样不仅可以替换元素,还可以替换整个数组实例。
另一方面,[In, Out] int[] arr
是按值传递的简单引用。如果本机端也使用单个间接寻址,请使用此选项。 int32_t* arr
。通常,在C#中,如果按值传递数组(这是引用类型),则被调用的方法可以替换元素,这将在调用方反映出来。但是,P /调用封送处理有点differently:
由于性能原因,默认情况下,默认情况下,按值传递的引用类型(类,数组,字符串和接口)将被编组为
In
参数。除非您将InAttribute
和OutAttribute
(或仅将OutAttribute
)应用于方法参数,否则您不会看到对这些类型的更改。
因此,无论指定Out
属性如何,本机端都能获得正确的指针。封送拆收器需要在此处指定[Out]
,这样它就不会忽略回传到托管内存的会话。
类似地,in int length
将传递对整数的引用,并且与[In] int length
相同,后者仅按值传递参数。可以省略[In]
,因为在这种情况下,这是默认的封送处理行为。