В собственной оболочке 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 для управления дескриптором к safehandle и прочитал, что это замена. Однако замена IntPtr подклассом SafeHandle в приведенном выше коде C# вызывает сообщение об исключении:
delegate void CallBackType(MySafeHandle instance, int argument);