我可以使用SafeHandle而不是IntPtr吗?

Dav*_*vio 16 c# pinvoke handle marshalling

我在网上广泛搜索但没有找到一个好的解释.

我的问题非常简单.

我有一个DLL,它有一个名为Initialize的函数,其中一个参数是一个指针,它将接收一个句柄,用于后续调用.另一个参数是一个字符串,我将列出完整性.我正在使用的签名是(简单形式):

[DllImport(MyDll)]
static extern bool Initialize([In] string name, out IntPtr handle);
Run Code Online (Sandbox Code Playgroud)

DLL本身的签名写为:Initialize(LPTSTR name, HANDLE handle)注释"HANDLE:指向将接收句柄的位置".

随后的电话采取的形式

[DllImport(MyDll)]
static extern bool DoSomething(IntPtr handle, uint randomParameter);
Run Code Online (Sandbox Code Playgroud)

我一直在阅读SafeHandle,我想知道我是否可以用它来替代我的IntPtr句柄.如果可以的话,我该怎么做?扩展抽象的SafeHandle类不是问题,但我可以直接用IntPtr替换SafeHandle(并使用默认编组)或者我是否需要做一些额外的事情?

LBu*_*kin 10

你可以找到一个更完整的答案,关于SafeHandleIntPtr这里之间的差异: IntPtr,SafeHandle和HandleRef - 解释

但是,总而言之,IntPtr应该在参数实际上是机器大小指针的SafeHandle地方使用- 应该在参数实际上是Win32句柄的地方使用.这些类型通常不可互换; IntPtr不同体系结构的大小会有所不同(x86为32位,x64为64位,amd64为64位).注意:我相信在封面下也SafeHandle使用了一个IntPtr).

此外,与IntPtr,SafeHandle其实当一个类被垃圾收集处置执行资源.这可以确保在程序运行时系统资源不会泄漏(尽管在可能Dispose()SafeHandle情况下应尽早提供实例).请注意,这SafeHandle实际上是抽象的,因为有许多不同类型的句柄需要不同的方法来进行适当的处​​理和处理.

在您的特定情况下,您需要查看您正在调用的DLL的文档.如果它是Win32 DLL,可能已经有一个SafeHandle类型.如果它是第三方DLL,那么您可以推出自己的SafeHandle实现 - 假设除了Initialize()某个版本Release()(或等效)之外.

关于IntPtr和SafeHandle的一些其他有趣的花絮可以在以下位置找到:

使用SafeHandle封装本机资源

SafeHandle类参考

SafeHandles和关键终结