C# 以SafeHandle作为参考参数的P/Invoke

C# 以SafeHandle作为参考参数的P/Invoke,c#,pinvoke,ref,safehandle,C#,Pinvoke,Ref,Safehandle,我在非托管Dll中有一个函数,它需要指向句柄的指针,例如: extern "C" __declspec(dllexport) BOOL __stdcall MySetEvent(HANDLE* handle, int size) { if (!handle) return FALSE; assert(sizeof(*handle) == size); printf("MySetEvent(%p, %d)\n", *handle, size); return Se

我在非托管Dll中有一个函数,它需要指向句柄的指针,例如:

extern "C" __declspec(dllexport) BOOL __stdcall MySetEvent(HANDLE* handle, 
int size)
{
    if (!handle) return FALSE;
    assert(sizeof(*handle) == size);
    printf("MySetEvent(%p, %d)\n", *handle, size);
    return SetEvent(*handle);
}
我如何从C#调用它,而不使用该示例中的危险GetHandle

[DllImport("UnmanagedDll", SetLastError = true)]
static extern int MySetEvent(ref IntPtr handle, int size);


AutoResetEvent ev = new AutoResetEvent(false);
var handle = ev.SafeWaitHandle.DangerousGetHandle();
MySetEvent(ref handle, Marshal.SizeOf(handle));
这不起作用(将引发.ctor的MissingMethodException):


修正C++代码,需要处理参数,而不是处理**。考虑到它没有做任何与AutoReTeEvServ.Stand()不同的事情,调用SETEVER()没有任何可想象的优势。C代码是第三方的,并做了一点。上面的代码只是解释问题的一个示例。“这不起作用”并不能解释任何事情。在我看来,DangerousGetHandle正是您所需要的。是的,名字里有“危险”,但那是因为你在做一件危险的事。该函数不是“正常的”,不需要吃指向句柄的指针,而真正需要的函数可能无法从托管代码中安全地调用(因为它希望挂起指针或更改指针)。如果您想“安全地”使用
DangerousGetHandle
,请阅读如何使用
DangerousAddRef
/
Release
或编写一些C++/CLI代码,以便更好地粘合C#和非托管DLL。
[DllImport("UnmanagedDll", SetLastError = true)]
static extern int MySetEvent([In] ref SafeHandle handle, int size);


SafeHandle handle = ev.SafeWaitHandle;
MySetEvent(ref handle,  Marshal.SizeOf(IntPtr.Zero));