2009-04-26 5 views
3

私は次の関数マーシャリング(アンマネージドタイプに構造を渡す)

long func(struct name * myname) 
{ 
    strcpy(myname->firstname,"rakesh"); 
    strcpy(myname->lastname,"agarwal"); 
    return S_OK; 
} 

struct name 
{ 
    char firstname[100]; 
    char lastname[100]; 
} 

を公開し、C++のDLLを持って、私はC#アプリケーションからこの関数を呼び出すにしたいので、私は次のようにします

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
unsafe public struct name 
{ 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=100)] 
    public string firstname; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] 
    public string lastname; 
} ; 


[DllImport("C++Dll.dll")] 
public unsafe static extern long func(name[] myname); 

name[] myname = new name[1]; 
func(myname); 

アプリケーションが正常に構築されます。 C#アプリケーション.exeが実行されると、関数func()が正常に呼び出され、dllの内部にフィールドを正常に埋め込むことができます。しかし、関数がC#アプリケーションに戻るとき、変数mynameは構造体フィールド(firstnamelastname)のnull値を引き続き満たします。

私はmynameのフィールド値を移入することができていますように、機能func()終了実行後、変数myname->firstnameは「ラケッシュ」が含まれているとmyname->lastnameは「Agarwalさん」が含まれるように(変更を提案してください

注:StringBuilderのを構造の内部で使用することはできません

答えて

3

public unsafe static extern long func(ref name myname)として輸入を宣言し、としてそれを呼び出す:。

name myname = new name(); 
func(ref myname); 

あなたはおそらく、名前の構造やインポート宣言に安全でない宣言を必要としないでしょう。

7

配列を使用する代わりに、参照によって構造体を渡します。 PInvoke呼び出しの場合、ref構造体は構造体へのポインタに変換されます。また、引数refはCLRに双方向、ネイティブコードへのデータのマーシャリングを指示し、その後再び取り消します。

[DllImport("C++Dll.dll")] 
public unsafe static extern long func(ref name myname); 

あなたが相互運用多くの仕事をやっている場合にも、私はあなたがのPInvoke相互運用アシスタント(link)をチェックしてください示唆しています。このツールは、大部分のC型定義(構造体、列挙型、共用体、関数ポインタを含む)を対応するC#またはVB.Net型に自動的に変換します。これらのタイプを含むシグネチャをさらに変換します。