以类型安全的方式发送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

在处理非托管内存时,每个定义都有发生"意外"的可能性。

也就是说,您可以将IntPtr封装在一个类中,就像Microsoft使用他们的SafeHandle类和相关的SafeFileHandleSafePipeHandle。。。等

您可以创建自己的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被处理时自动完成的。