[英]Marshal an IntPtr in a typesafe manner
我有以下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
包裝在一個類中,就像微軟用他們的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
時自動完成的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.