元Mar C ++“ string” C#P / Invokeのクラス
-
03-07-2019 - |
質問
次のように定義されたネイティブDLLに関数があります:
#include <string>
void SetPath(string path);
これをMicrosoftのP / Invoke Interop Assistantに入れようとしましたが、&quot; string&quot;クラス(MFCからですか?)。
さまざまなタイプ(C#String、char []、byte [])としてマーシャリングしようとしましたが、NotSupportedExceptionまたはNative Assembly Exceptionを受け取るたびに(試したマーシャリングに応じて)。
ネイティブ文字列クラスが使用されるネイティブ/マネージド相互運用を行ったことがありますか?これを元sにする方法はありますか?独自のマーシャラーを作成する必要がありますか?
解決
C ++標準ライブラリ文字列クラスを使用しようとしているようです。それは元Marに簡単だとは思わない。文字*とMarshalをStringBuilderとして使用することをお勧めします。それは私が通常行うことです。 C ++文字列を生成するラッパーを追加する必要があります。
他のヒント
PInvoke相互運用アシスタントは、C ++ではなくCのみをサポートします。残念ながら、MFC Stringクラス(CStringは信じますか?)はC ++であり、アシスタントでは機能しません。代わりに、次を使用してみてください
void SetPath(__in const WCHAR* path);
はい。あなたはできる。実際、 std :: string
、 std :: wstring
だけでなく、標準のC ++クラスまたは独自のクラスをマーシャリングまたはインスタンス化して、C#/。NETから呼び出すことができます
.NETワールドからC ++オブジェクトをインスタンス化する基本的な考え方は、.NETからC ++オブジェクトの正確なサイズを割り当て、C ++ DLLからエクスポートされたコンストラクターを呼び出してオブジェクトを初期化することです。関数のいずれかを呼び出してそのC ++オブジェクトにアクセスします。メソッドのいずれかが他のC ++クラスを含む場合、それらをC#クラスでラップする必要があります。プリミティブ型のメソッドの場合は、単純にP / Invokeを実行できます。呼び出すメソッドが数個しかない場合は簡単で、手作業でコーディングするのに時間がかかりません。 C ++オブジェクトの処理が完了したら、C ++オブジェクトのデストラクターメソッドを呼び出します。これは、エクスポート関数でもあります。メモリがない場合は、.NETからメモリを解放するだけです。
例を次に示します。
public class SampleClass : IDisposable
{
[DllImport("YourDll.dll", EntryPoint="ConstructorOfYourClass", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void SampleClassConstructor(IntPtr thisObject);
[DllImport("YourDll.dll", EntryPoint="DoSomething", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void DoSomething(IntPtr thisObject);
[DllImport("YourDll.dll", EntryPoint="DoSomethingElse", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)]
public extern static void DoSomething(IntPtr thisObject, int x);
IntPtr ptr;
public SampleClass(int sizeOfYourCppClass)
{
this.ptr = Marshal.AllocHGlobal(sizeOfYourCppClass);
SampleClassConstructor(this.ptr);
}
public void DoSomething()
{
DoSomething(this.ptr);
}
public void DoSomethingElse(int x)
{
DoSomethingElse(this.ptr, x);
}
public void Dispose()
{
Marshal.FreeHGlobal(this.ptr);
}
}
詳細については、以下のリンクをご覧ください。
(私はSDKツールの作成者です)
C ++クラスのC#ラッパークラスが準備できたら、 ICustomMarshaler
を簡単に実装できるため、.NETからC ++オブジェクトをマーシャリングできます。
http://msdn.microsoft.com/ en-us / library / system.runtime.interopservices.icustommarshaler.aspx