【问题标题】:What is the difference between [In, Out] and ref when using pinvoke in C#?在 C# 中使用 pinvoke 时 [In, Out] 和 ref 有什么区别?
【发布时间】:2016-02-22 06:25:15
【问题描述】:

将参数从 C# 传递到 C++ 时,使用 [In, Out] 和仅使用 ref 有区别吗?

我发现了几个不同的 SO 帖子,以及来自 MSDN 的一些内容,这些内容与我的问题很接近,但并没有完全回答。我的猜测是我可以像使用 [In, Out] 一样安全地使用 ref,并且编组器的行为不会有任何不同。我担心它的行为会有所不同,并且 C++ 不会对我的 C# 结构被传递感到满意。我已经在我正在工作的代码库中看到了这两件事......

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

Are P/Invoke [In, Out] attributes optional for marshaling arrays? 让我觉得我应该使用 [In, Out]。

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

【问题讨论】:

  • 能否举个具体的例子。您想知道[In, Out] ref int fooref int foo 之间的区别吗?就目前而言,您的问题缺乏细节,我相信您需要一个(或多个)具体示例。
  • 类似的,是:[DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool myFunction([In, Out] SomeStruct[] aStruct; 和使用 ref 一样代替 [In, Out]。
  • 另外,你是把 [In, Out] 和 ref ;) 结合起来了吗?
  • 不,它们不一样。

标签: c# pinvoke


【解决方案1】:

refout 的使用不是任意的。如果本机代码需要按引用传递(指针),那么如果参数类型是值类型,您必须使用这些关键字。这样抖动就知道生成指向该值的指针。如果参数类型是引用类型(类),您必须省略它们,对象已经是引擎盖下的指针。

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

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

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

只要明确并在需要时始终使用 [Out]。如果事实证明没有必要,它不会花费任何费用。它是自我记录的。如果原生代码的架构发生变化,你会觉得它仍然可以工作。

【讨论】:

  • 我很确定我的对象不是 blittable (尽管我不肯定)。如果我有一些当前是 [In, Out] 的东西,是否将其更改为仅使用 [Out] 是更简洁的代码并且行为方式相同?或者留下 [In, Out] 属性以显示双向意图会更简洁吗?感谢您的回答。
  • 如果意图是双向的,那么就这样描述它,使用[In, Out]。
  • 如果值是 blittable 而不是引用类型(在这种情况下,C# 中的结构),将使用 ref 而不是使用 [In, Out] 工作,因为结构是顺序的并且只包含原始类型(int、float、double)?这是否与对编组器使用 [In, Out] 相同,因为在任何一种情况下,它都会将对象固定在内存中?
  • 您没看懂答案,使用ref 不是可选的,不能用[In, Out] 代替。如果本机代码需要一个指针并且 需要 使用 ref,则您必须生成一个指针。 下一个考虑是描述数据流的属性。
  • 您可以在docs.microsoft.com找到此信息
猜你喜欢
  • 1970-01-01
  • 2010-09-28
  • 1970-01-01
  • 2019-02-21
  • 1970-01-01
  • 2014-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多