在C#中使用pinvoke时,[In,Out]和ref有什么区别? [英] What is the difference between [In, Out] and ref when using pinvoke in C#?

查看:459
本文介绍了在C#中使用pinvoke时,[In,Out]和ref有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is there a difference between using [In, Out] and just using ref when passing parameters from C# to C++?

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

I've found a couple different SO posts, and some stuff from MSDN as well that comes close to my question but doesn't quite answer it. My guess is that I can safely use ref just like I would use [In, Out], and that the marshaller won't act any differently. My concern is that it will act differently, and that C++ won't be happy with my C# struct being passed. I've seen both things done in the code base I'm working in...

这是我找到并正在阅读的帖子:

Here are the posts I've found and have been reading through:

是P/调用[In,Out]封送数组的可选属性是什么? 让我觉得我应该使用[In,Out].

Are P/Invoke [In, Out] attributes optional for marshaling arrays? Makes me think I should use [In, Out].

  • MSDN: InAttribute
  • MSDN: OutAttribute
  • MSDN: Directional Attributes

这三篇文章使我认为我应该使用[In,Out],但是我可以改用ref,并且它将具有相同的机器代码.那让我觉得我错了-因此在这里提问.

These three posts make me think that I should use [In, Out], but that I can use ref instead and it will have the same machine code. That makes me think I'm wrong -- hence asking here.

推荐答案

refout的使用不是任意的.如果本机代码要求传递引用(指针),则如果参数类型是值类型,则必须使用这些关键字.使抖动知道生成指向该值的指针.而且,如果参数类型是引用类型(类),则必须忽略它们,而对象已经是幕后的指针.

The usage of ref or out is not arbitrary. If the native code requires pass-by-reference (a pointer) then you must use those keywords if the parameter type is a value type. So that the jitter knows to generate a pointer to the value. And you must omit them if the parameter type is a reference type (class), objects are already pointers under the hood.

然后需要[In]和[Out]属性来解决有关指针的歧义,它们没有指定数据流. [In]始终由pinvoke编组器隐含,因此不必明确说明.但是,如果您希望看到本机代码对代码中的结构或类成员所做的任何更改,则必须使用[Out]. Pinvoke编组器避免自动复制回去,以免产生费用.

The [In] and [Out] attributes are then necessary to resolve the ambiguity about pointers, they don't specify the data flow. [In] is always implied by the pinvoke marshaller so doesn't have to be stated explicitly. But you must use [Out] if you expect to see any changes made by the native code to a struct or class member back in your code. The pinvoke marshaller avoids copying back automatically to avoid the expense.

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

A further quirk then is that [Out] is not often necessary. Happens when the value is blittable, an expensive word that means that the managed value or object layout is identical to the native layout. The pinvoke marshaller can then take a shortcut, pinning the object and passing a pointer to managed object storage. You'll inevitably see changes then since the native code is directly modifying the managed object.

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

Something you in general strongly want to pursue, it is very efficient. You help by giving the type the [StructLayout(LayoutKind.Sequential)] attribute, it suppresses an optimization that the CLR uses to rearrange the fields to get the smallest object. And by using only fields of simple value types or fixed size buffers, albeit that you don't often have that choice. Never use a bool, use byte instead. There is no easy way to find out if a type is blittable, other than it not working correctly or by using the debugger and compare pointer values.

只是明确的,在需要时始终使用[Out].如果事实证明没有必要,那么它不会花费任何费用.它是自我记录.而且,您可以感觉到,如果本机代码的体系结构发生更改,它仍然可以正常工作.

Just be explicit and always use [Out] when you need it. It doesn't cost anything if it turned out not to be necessary. And it is self-documenting. And you can feel good that it still will work if the architecture of the native code changes.

这篇关于在C#中使用pinvoke时,[In,Out]和ref有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆