私はC++でこのコードを持っています
class MyClass { ... };
typedef MyClass (*Callback)();
Callback theCB;
static void RegisterCallback( Callback cb ) { theCB = cb; };
static void CallCallback() {
MyClass obj = theCB();
}
私はswigを使用していますが、簡単にするために(swigがわからない場合)、C#でこのラッパーを使用しています
public class MyClassWrapper
{
public IntPtr ptrToNativeObj; // pointer to native MyClass object
public MyClassWrapper()
{
ptrToNativeObj = call to native code that creates
and returns a new instance of MyClass in C++
}
};
ここで、C# でコールバック メカニズムをサポートしたいので、次のように設定します。
public MyClassWrapper MyFunction()
{
return new MyClassWrapper();
}
delegate MyClassWrapper CallbackDotNet();
static void main()
{
var fct = new CallbackDotNet( MyFunction );
P/Invoke call to native function RegisterCallback( fct );
then finally:
P/Invoke call to native function CallCallback();
}
このコードはすべて正しく動作するように設定されています。CallCallback のネイティブ コードは MyFunction を適切に呼び出します。
しかし、返されたオブジェクトを適切に処理する必要があります...
MyFunction は、C++ のコールバックが値によって返されている間に C# 参照を返すため、これは無料では機能しません。
static void CallCallback() {
MyClass obj = theCB();
}
MyFunction から返された MyClassWrapper オブジェクトへの「参照」をマーシャリングして、C++ が MyClass オブジェクトを「値渡し」で受け取るようにするにはどうすればよいですか?
先に進んでカスタム マーシャラーを作成する必要がありますか?
http://msdn.microsoft.com/en-us/library/zk0a8dea(v=vs.90).aspx
次に、ここのように使用します
[return: MarshalAs(UnmanagedType.CustomMarshaler,
MarshalType = "MyCustomMarshaler")]
delegate MyClassWrapper CallbackDotNet();
カスタム マーシャラーのドキュメントを見たところ、非常に複雑です。実装する興味深い方法は次のとおりです。
IntPtr MarshalManagedToNative( Object ManagedObj );
そして、コードは次のようになります
IntPtr MarshalManagedToNative( Object ManagedObj )
{
MyClassWrapper val = ManagedObj as MyClassWrapper;
return val.ptrToNativeObj;
}
しかし、これは、この C++ コードが期待する MyClass 値ではなく、MyClass* をネイティブ コードに返します。
static void CallCallback() {
MyClass obj = theCB();
}
マーシャラーは、ポインターを逆参照するのに十分賢いでしょうか?