关键字`in,out,ref` vs Attributes`[In],[Out],[In,Out]`

时间:2019-05-12 07:53:39

标签: c# marshalling

我知道第一组关键字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);

是否有两组不相等的情况?

1 个答案:

答案 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参数。除非您将InAttributeOutAttribute(或仅将OutAttribute)应用于方法参数,否则您不会看到对这些类型的更改。

因此,无论指定Out属性如何,本机端都能获得正确的指针。封送拆收器需要在此处指定[Out],这样它就不会忽略回传到托管内存的会话。

类似地,in int length将传递对整数的引用,并且与[In] int length相同,后者仅按值传递参数。可以省略[In],因为在这种情况下,这是默认的封送处理行为。