gpt4 book ai didi

c# - 在 C# 中使用 pinvoke 时 [In, Out] 和 ref 有什么区别?

转载 作者:IT王子 更新时间:2023-10-29 04:43:46 25 4
gpt4 key购买 nike

在将参数从 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 并且它将具有相同的机器代码。这让我觉得我错了 - 因此在这里问。

最佳答案

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

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

另一个怪癖是 [Out] 不是经常需要的。当值为 blittable 时发生,这是一个昂贵的词,表示托管值或对象布局与 native 布局相同。然后 pinvoke 编码器可以走捷径,固定对象并将指针传递给托管对象存储。由于 native 代码直接修改托管对象,因此您将不可避免地看到更改。

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

只需明确说明,并在需要时始终使用 [Out]。如果事实证明没有必要,它不会花费任何费用。它是 self 记录的。如果 native 代码的体系结构发生变化,它仍然可以工作,您会感觉很好。

关于c# - 在 C# 中使用 pinvoke 时 [In, Out] 和 ref 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33815276/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com