以下は、架空のライブラリlibfooを操作するハンドルをラップするクラスLibFooHandleを作成し、usingステートメントと組み合わせて使用する例です。 この例に登場する架空のライブラリlibfooには、以下のようなAPI関数が用意されているものと想定します。

foo_t* foo_create_handle()
libfooの操作関数を呼び出すためのインスタンスハンドルを作成する。
bool foo_release_handle(foo_t* handle)
libfooのインスタンスハンドルを解放する。
void foo_do_something(foo_t* handle)
libfooのインスタンスハンドルに対してなんらかの操作を行う。

なお、例示のためAPI呼び出しに付随して想定される例外等の考慮・処理は省略しています。

SafeHandleクラスを使ってライブラリのハンドルをラップする
Imports System
Imports System.Runtime.InteropServices

' libfooのAPIセットをDllImportしたものを想定したモジュール
Module libfoo
  ' <DllImport("libfoo")>
  Public Function foo_create_handle() As IntPtr
    Return New IntPtr(1)
  End Function

  ' <DllImport("libfoo")>
  Public Function foo_release_handle(ByVal handle As IntPtr) As Boolean
    Return True
  End Function

  ' <DllImport("libfoo")>
  Public Sub foo_do_something(ByVal handle As IntPtr)
    Console.WriteLine(handle)
  End Sub
End Module

' libfooのハンドルをラップするSafeHandle
Public NotInheritable Class LibFooHandle
  Inherits SafeHandle

  Public Overrides ReadOnly Property IsInvalid As Boolean
    Get
      Return handle = IntPtr.Zero ' handleの値が0の場合、無効として扱う
    End Get
  End Property

  Private Sub New(ByVal handle As IntPtr)
    MyBase.New(IntPtr.Zero, ownsHandle := True)

    SetHandle(handle)
  End Sub

  Public Shared Function Create() As LibFooHandle
    ' foo_create_handle関数が返すハンドルをラップしてLibFooHandleとして返す
    Return New LibFooHandle(libfoo.foo_create_handle())
  End Function

  Protected Overrides Function ReleaseHandle() As Boolean
    ' foo_release_handle関数を呼びハンドルを解放する
    Return libfoo.foo_release_handle(Me.handle)

    ' このあとhandleには無効値(IntPtr.Zero)が設定され、IsInvalidがTrueとなる
    ' IsInvalidがTrueの場合ReleaseHandleは呼び出されなくなるので、二重解放は起こらない
  End Function

  Public Sub DoSomething()
    If IsInvalid Then Throw New InvalidOperationException("handle is invalid")

    ' foo_do_something関数を呼びハンドルに対して操作を行う
    libfoo.foo_do_something(Me.handle)
  End Sub
End Class

Class Sample
  Shared Sub Main()
    ' libfooのハンドルを作成する
    Using handle As LibFooHandle = LibFooHandle.Create()

      ' libfooのハンドルを使って何らかの操作を行う
      handle.DoSomething()

    End Using ' 必要なくなった時点でlibfooのハンドルを解放する
  End Sub
End Class

.NET Core 3.0以降では、ネイティブライブラリのロードに、DllImport属性だけでなくNativeLibraryクラスを使用することができるようになっています。

MENTAにてテキストチャットによるサポートを行っています。 問題の解決法をお探しの方や.NET/C#を学習中の方はどうぞご利用ください。