2015-11-19 27 views
13

[In、Out]を使用する場合と、C#からC++にパラメータを渡すときにrefを使用するだけの違いはありますか?C#でpinvokeを使用するときの[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を使用できることを確認し、それは同じになりますマシンコード。それは私が間違っていると思うので、ここで尋ねる。

+0

具体的な例を挙げてください。 '[In、Out] ref int foo'と' ref int foo'の違いを知りたいですか?それが立てば、あなたの質問には詳細が不足しています。私はあなたが1つ(またはそれ以上)の具体的な例が必要だと考えています。 –

+0

次のようなものがあります:[DllImport( "MyDll.dll"、CallingConvention = CallingConvention.Cdecl)] private static extern bool myFunction([In、Out] SomeStruct [] aStruct; [In 、Out]。 – PerryC

+0

また、[In、Out]とref;を組み合わせただけですか? – PerryC

答えて

14

refまたはoutの使用は、ではなく、です。ネイティブコードで参照渡し(ポインタ)が必要な場合は、で、パラメータ型が値型の場合はそれらのキーワードを使用する必要があります。その結果、ジッタは値へのポインタを生成することがわかります。 パラメータタイプが参照型(クラス)の場合、オブジェクトはすでにフードの中のポインタになっています。

ポインタのあいまいさを解決するには[In]と[Out]属性が必要ですが、データフローは指定しません。 [In]はピンボケ・マーシャルによって常に暗示されるので、明示的に述べる必要はありません。しかし、でなければなりません。ネイティブコードによって変更された構造体またはクラスメンバーがコード内に戻ってくることが予想される場合は、[Out]を使用する必要があります。 pinvoke marshallerは自動的にコストを避けるためにコピーバックしません。

さらに、[Out]はしばしば必要ではないということです。値がblittableである場合に発生します。高価な言葉は、管理された値またはオブジェクトのレイアウトがネイティブレイアウトと同一であることを意味します。 pinvoke marshallerは、ショートカットを作成して、オブジェクトを固定し、管理オブジェクトストレージにポインタを渡すことができます。ネイティブコードが管理対象オブジェクトを直接変更しているので、必然的に変更が表示されます。

あなたが一般に強く求めているものは、非常に効率的です。 [StructLayout(LayoutKind.Sequential)]属性を指定すると、最小のオブジェクトを取得するためにフィールドを再配置するためにCLRが使用する最適化が抑制されます。また、単純な値型または固定サイズのバッファーのフィールドだけを使用することで、その選択肢がしばしばありません。 ブールを使用しないでください。代わりにバイトを使用してください。正しく動作しないか、デバッガを使用してポインタ値を比較する以外に、型がblittableかどうかを調べる簡単な方法はありません。

必要なときに[Out]を使用してください。それが必要でないことが判明した場合は、何の費用もかかりません。そしてそれは自己文書化です。ネイティブコードのアーキテクチャーが変更されても、それが機能するということは気になります。

+0

私のオブジェクトはblittableではないと確信しています(ただし、私は肯定的ではありません)。私が現在[In、Out]であるものを持っていれば、[Out]を使ってコードをより綺麗にし、同じように振る舞います。または、[In、Out]属性をそのままにして双方向の意図を示すようにすると、よりクリーンなコードになりますか?ご回答有難うございます。 – PerryC

+2

もし双方向が意図ならば、それをそのように記述し、* do * [In、Out]を使う。 –

+0

値がblittableで、参照型(この場合はC#の構造体)ではなく、構造体がシーケンシャルであり、プリミティブ型(int、float、ダブル)?これは、どちらの場合でもオブジェクトをメモリに固定するため、マーシャルに[In、Out]を使用するのと同じでしょうか? – PerryC

関連する問題