在我正在编写的本机 dll 包装器中,我刚刚用 SafeHandles 替换了 IntPtr 的所有用法(用于编组句柄)。我的印象是正确编写的 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);