以类型安全的方式发送IntPtr
本文关键字:IntPtr 方式发 类型安全 | 更新日期: 2023-09-27 18:25:29
我有以下c函数
opaque_struct* create() {}
void free(opaque_struct*) {}
我想使用PInvoke:呼叫
[DllImport("test")]
public static extern IntPtr create ();
[DllImport("test")]
public static extern void free (IntPtr);
我想这会很好,但我正在寻找一种方法,在托管代码中明确声明"free"只接受"create"返回的IntPtr,并避免意外传递从其他函数接收的其他IntPtr。
就所有托管代码而言,指向的结构是不透明的。
即使我所做的只是给它一个新名称,没有额外的属性,也不可能扩展IntPtr。
有什么方法可以把这个类型化为IntPtr吗?
在处理非托管内存时,每个定义都有发生"意外"的可能性。
也就是说,您可以将IntPtr
封装在一个类中,就像Microsoft使用他们的SafeHandle类和相关的SafeFileHandle
、SafePipeHandle
。。。等
您可以创建自己的SafeHandle
类(可以从System.Runtime.InteropServices.SafeHandle
继承),并在p/Invoke声明中使用它:
[DllImport("test")]
public static extern MySafeHandle create ();
[DllImport("test")]
public static extern void free (MySafeHandle pointer);
SafeHandle
的另一个好处是它实现了IDisposable
,因此允许使用using
语句来确保您的free()
方法始终调用:
using (MySafeHandle ptr = create())
{
// Use your ptr instance here
// You can retrieve the IntPtr value itself using
// ptr.DangerousGetHandle()
// When you get out of the scope of the using(), the MySafeHandle
// object will be disposed and ptr.ReleaseHandle() will be called.
// Just add your call to free() in the overriden ReleaseHandle method
}
正如您所看到的,它甚至不需要手动调用free()
,因为它是在SafeHandle
被处理时自动完成的。