2009-08-03 18 views
3

は、私はC++の構造体のPInvokeエラー

struct UnmanagedStruct 
{ 
    char* s; 
    // Other members 
};

およびC++ライブラリは

extern "C" UnmanagedStruct __declspec(dllexport) foo(char* input); 

を公開

struct ManagedStruct { 
    [MarshalAs(UnmanagedType.LPStr)] 
    string s; 
    // Other members 
}

C#の構造体を持っており、それがあります輸入品

[DllImport("SomeDLL.dll", CharSet = CharSet.Ansi)] 
    static extern ManagedStruct foo(string input); 

私はこの関数を呼び出すときしかし、私は

MarshalDirectiveExceptionを取得するには、

メソッドの型シグネチャはPInvokeの互換性がない未処理でした。

この関数呼び出しは、構造体からchar *と文字列sを削除すると機能します。

答えて

4

このようなシナリオでは、文字列を直接使用しないでください。代わりに型をIntPtr値に変更し、必要に応じてMarshal.PtrToStringAuto/Ansi/Uniを使用します。この場合、ネイティブコードはchar*を使用するため、PtrToStringAnsiが最適です。

struct ManagedStruct { 
    IntPtr s; 
    public string sAsString { get { return Marshal.PtrToStringAnsi(s); } } 
} 
+0

なぜ私はそれを行う必要がありますか?私は早くこの質問をして、人々はすべてそれが「うまくいく」と言っていた。 – DevDevDev

+0

@SteveM、strings + PInvoke =困難です。ストリングは多くのシナリオで機能しますが、他の多くのシナリオでは失敗します。構造体のフィールドとしての文字列は、メモリ管理の大きな問題があるため特に困難です。特に、管理された文字列を作成するために使用されたメモリをCLRでどのように処理する必要がありますか?それを解放するか、何もしないでください。一般的に、CLRがこのようなものを見ると、データを解放してCoTaskMemFreeをあなたのシナリオでおそらく間違っている値で呼び出す必要があると仮定します。 – JaredPar

+0

(続き)。一般に、文字列をマーシャリングする方法(とインライン配列ではない)を混乱させる場合は、IntPtrを使用して文字列を手作業でマーシャリングします。これははるかに良い仕事のチャンスを持っています – JaredPar

関連する問題