我有以下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
时自动完成。
关于c# - 以类型安全的方式编码(marshal) IntPtr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9377101/