私が書いているネイティブdllラッパーでは、IntPtrのすべての使用法(ハンドルをマーシャリングするため)をSafeHandlesに置き換えました。このように、正しく記述されたSafeHandle型はIntPtrと互換性があるという印象を受けました。
ただし、Marshal.GetFunctionPointerForDelegate呼び出しで例外がスローされるようになりました。
Cannot marshal 'parameter #n': SafeHandles cannot be marshaled from unmanaged to managed.
コールバックには引数リストにハンドルが含まれているため、デリゲートにはその場所にSafeHandleが含まれています(以前のIntPtrではありません)。だから私はこれをすることはできませんか?もしそうなら、コールバックをマーシャリングする必要があるとすると、SafeHandlesを使用するための私のオプションは何ですか?
ネイティブdllヘッダーの編集例を次に示します。
struct aType aType;
typedef void (*CallBackType)(aType*, int);
aType* create(); // Must be released
void release(aType* instance);
int doSomething(aType* instance, int argumnet);
void setCallback(CallbackType func);
私に問題を引き起こしているのはコールバックです。C#側は次のようになりました。
delegate void CallBackType(IntPtr instance, int argument);
それで:
var funcPtr = Marshal.GetFunctionPointerForDelegate(del = new CallbackType(somefunc)):
NativeFunction.setCallback(funcPtr)
これは正常に機能し、常に実行されていました。ただし、ハンドルを管理するためのIntPtrからセーフハンドルに移行したかったので、交換のドロップであると読みました。ただし、上記のC#コードでIntPtrをSafeHandleサブクラスに置き換えると、報告される例外が発生します。
delegate void CallBackType(MySafeHandle instance, int argument);