在 C# 中使用 pinvoke 时 [In, Out] 和 ref 有什么区别?
What is the difference between [In, Out] and ref when using pinvoke in C#?
在将参数从 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 并且它将具有相同的机器代码。这让我觉得我错了 - 因此在这里问。
ref
或 out
的用法 不是 任意的。如果本机代码需要按引用传递(指针),那么如果参数类型是值类型,则您 必须 使用这些关键字。这样抖动就知道生成一个指向该值的指针。如果参数类型是引用类型 (class),你 必须 省略它们,对象已经是指针。
然后 [In] 和 [Out] 属性是解决指针歧义所必需的,它们不指定数据流。 [In] 始终由 pinvoke 编组器暗示,因此不必明确说明。但是,如果您希望在代码中看到本机代码对结构或 class 成员所做的任何更改,则您 必须 使用 [Out]。 pinvoke marshaller 避免自动回写以避免开销。
另一个怪癖是 [Out] 通常不是必需的。当值为 blittable 时发生,这是一个昂贵的词,表示托管值或对象布局与本机布局相同。然后 pinvoke 编组器可以走捷径,固定对象并将指针传递给托管对象存储。由于本机代码直接修改托管对象,因此您将不可避免地看到更改。
你一般都非常想追求的东西,效率很高。您可以通过为类型提供 [StructLayout(LayoutKind.Sequential)] 属性来提供帮助,它可以抑制 CLR 用于重新排列字段以获得最小对象的优化。并且仅使用简单值类型的字段或固定大小的缓冲区,尽管您通常没有这种选择。切勿使用 bool,而是使用 byte。没有简单的方法可以查明类型是否可 blittable,除非它不能正常工作或使用调试器并比较指针值。
只要明确一点,并在需要时始终使用 [Out]。如果事实证明没有必要,它不会花费任何费用。它是自我记录的。如果本机代码的体系结构发生变化,它仍然可以工作,你会感觉很好。
在将参数从 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 并且它将具有相同的机器代码。这让我觉得我错了 - 因此在这里问。
ref
或 out
的用法 不是 任意的。如果本机代码需要按引用传递(指针),那么如果参数类型是值类型,则您 必须 使用这些关键字。这样抖动就知道生成一个指向该值的指针。如果参数类型是引用类型 (class),你 必须 省略它们,对象已经是指针。
然后 [In] 和 [Out] 属性是解决指针歧义所必需的,它们不指定数据流。 [In] 始终由 pinvoke 编组器暗示,因此不必明确说明。但是,如果您希望在代码中看到本机代码对结构或 class 成员所做的任何更改,则您 必须 使用 [Out]。 pinvoke marshaller 避免自动回写以避免开销。
另一个怪癖是 [Out] 通常不是必需的。当值为 blittable 时发生,这是一个昂贵的词,表示托管值或对象布局与本机布局相同。然后 pinvoke 编组器可以走捷径,固定对象并将指针传递给托管对象存储。由于本机代码直接修改托管对象,因此您将不可避免地看到更改。
你一般都非常想追求的东西,效率很高。您可以通过为类型提供 [StructLayout(LayoutKind.Sequential)] 属性来提供帮助,它可以抑制 CLR 用于重新排列字段以获得最小对象的优化。并且仅使用简单值类型的字段或固定大小的缓冲区,尽管您通常没有这种选择。切勿使用 bool,而是使用 byte。没有简单的方法可以查明类型是否可 blittable,除非它不能正常工作或使用调试器并比较指针值。
只要明确一点,并在需要时始终使用 [Out]。如果事实证明没有必要,它不会花费任何费用。它是自我记录的。如果本机代码的体系结构发生变化,它仍然可以工作,你会感觉很好。