在C#中使用pinvoke时,[In,Out]和ref之间有什么区别? 在从C→C++到传递参数时,使用[in,OUT]和使用ReF有区别吗?

在C#中使用pinvoke时,[In,Out]和ref之间有什么区别? 在从C→C++到传递参数时,使用[in,OUT]和使用ReF有区别吗?,c#,pinvoke,C#,Pinvoke,我发现了一些不同的SO帖子,还有一些来自MSDN的东西,它们接近我的问题,但没有完全回答我的问题。我的猜测是,我可以像使用[In,Out]一样安全地使用ref,而且元帅的行为不会有任何不同。我担心的是,它会有不同的行为,C++对我的C结构不满意。我在我工作的代码库中看到了这两件事 以下是我找到并阅读的帖子: 让我觉得我应该使用[输入,输出] 这三篇文章让我觉得我应该使用[In,Out],但我可以使用ref,它将具有相同的机器代码。这让我觉得我错了——因此在这里问。使用ref或out不

我发现了一些不同的SO帖子,还有一些来自MSDN的东西,它们接近我的问题,但没有完全回答我的问题。我的猜测是,我可以像使用[In,Out]一样安全地使用ref,而且元帅的行为不会有任何不同。我担心的是,它会有不同的行为,C++对我的C结构不满意。我在我工作的代码库中看到了这两件事

以下是我找到并阅读的帖子:

让我觉得我应该使用[输入,输出]


这三篇文章让我觉得我应该使用[In,Out],但我可以使用ref,它将具有相同的机器代码。这让我觉得我错了——因此在这里问。

使用
ref
out
不是随意的。如果本机代码需要按引用传递(指针),那么如果参数类型是值类型,则必须使用这些关键字。以便抖动知道如何生成指向该值的指针。如果参数类型是引用类型(类),那么必须忽略它们,因为对象已经是隐藏的指针

[In]和[Out]属性对于解决指针的不确定性是必需的,它们不指定数据流。[In]始终由pinvoke marshaller暗示,因此无需明确说明。但是,如果希望在代码中看到本机代码对结构或类成员所做的任何更改,则必须使用[Out]。pinvoke marshaller避免自动复制回以避免费用

另一个怪癖是,通常不需要[退出]。当值为blittable时发生,这是一个昂贵的词,表示托管值或对象布局与本机布局相同。pinvoke marshaller然后可以采用快捷方式,固定对象并将指针传递到托管对象存储。您将不可避免地看到更改,因为本机代码正在直接修改托管对象

一般来说,你非常想追求的东西,是非常有效的。通过将[StructLayout(LayoutKind.Sequential)]属性赋予该类型,它将抑制CLR用于重新排列字段以获得最小对象的优化。并且只使用简单值类型的字段或固定大小的缓冲区,尽管您通常没有这样的选择。永远不要使用bool,而是使用byte。除了类型工作不正常或使用调试器和比较指针值之外,没有简单的方法来确定类型是否可blittable


只是要明确,在需要的时候总是使用[Out]。如果结果证明不是必要的,它不需要任何费用。这是自我记录。如果本机代码的体系结构发生变化,它仍然可以工作,您会感觉很好。

请给出一个具体的例子。您想知道
[In,Out]ref int foo
ref int foo
之间的区别吗?目前,你的问题缺乏细节,我相信你需要一个(或多个)具体的例子。比如:[DllImport(“MyDll.dll”,CallingConvention=CallingConvention.Cdecl)]私有静态extern bool myFunction([In,Out]SomeStruct[]aStruct;与使用ref代替[In,Out]相同。另外,你刚刚合并了吗[In,Out]和ref;)?不,它们不一样。我相当确定我的对象不可blittable(尽管我不是肯定的)。如果我有一些当前为[In,Out]的对象,将其更改为仅使用[Out]会是更干净的代码并以同样的方式运行吗?还是保留[In,Out]会是更干净的代码属性来显示双向意图?谢谢你的回答。如果双向是意图,那么就用[In,Out]来描述它。如果该值是可blittable的,而不是引用类型(在本例中是C#中的结构),那么如果该结构是连续的,并且只包含基元类型(int、float、double),使用ref而不是[In、Out]会起作用吗?这是否与对封送拆收器使用[In,Out]相同,因为在这两种情况下,它都会将对象固定在内存中?您不理解答案,使用
ref
不是可选的,不能用[In,Out]代替。如果本机代码需要指针,并且需要使用ref,则必须生成指针。接下来要考虑的是描述数据流的属性。您可以在