Imports System.Runtime.InteropServices
Imports System.ComponentModel
Namespace DynamicPInvoke
'''
''' DynamicPInvokerはアンマネージDLLの動的なロードと関数の呼び出しをサポートします。
'''
Public Class DynamicPInvoker
Implements IDisposable
#Region "WinAPI宣言部"
Friend Shared Function LoadLibrary( lpFileName As String) As IntPtr
End Function
Friend Shared Function FreeLibrary(hModule As IntPtr) As Boolean
End Function
Friend Shared Function GetProcAddress(hModule As IntPtr, lpProcName As String) As IntPtr
End Function
#End Region
Private hModule As IntPtr
#Region "コンストラクタ"
'''
''' オブジェクトの新しいインスタンスを初期化します。
''' ひとつのインスタンスにつきひとつのDLLを使用することが出来ます。
'''
''' ロードするDLLの名前またはファイルパスを指定します。
Public Sub New(dllname As String)
hModule = LoadLibrary(dllname)
End Sub
#End Region
#Region "パブリックメンバー"
'''
''' アンマネージDLLへの呼び出しが可能かどうかを示す値を取得します。
''' Disposeメソッドの呼出し後や、ライブラリのロードに失敗した場合、このプロパティはFalseを返します。
'''
Public ReadOnly Property IsAlive() As Boolean
Get
Return Not Me.bDisposed AndAlso (hModule IntPtr.Zero)
End Get
End Property
'''
''' インスタンスがロードしているライブラリに含まれる関数を呼び出すためのSystem.Delegateを取得します。
'''
''' System.Delegateによって呼び出す関数名で定義されたデリゲートの型を指定します。
''' 関数のポインタが取得できない場合、このメソッドはnull(VBではNothing)を返します。
Public Function GetDelegate(delegateType As Type) As System.Delegate
If IfDisposed(hModule) = IntPtr.Zero Then
Throw New Win32Exception("ライブラリがロードされていません。")
End If
' 関数ポインタを取得
Dim funcptr As IntPtr = GetProcAddress(hModule, delegateType.Name)
' 取得できなければnullを返す
If funcptr = IntPtr.Zero Then
Return Nothing
End If
' 関数ポインタからデリゲートを生成して返す
Return Marshal.GetDelegateForFunctionPointer(funcptr, delegateType)
End Function
'''
''' インスタンスがロードしているライブラリに含まれる関数を呼び出すためのSystem.Delegateを取得します。
'''
''' 呼び出す関数名で宣言されたデリゲートを指定します。
''' 関数を呼び出すためのデリゲートを格納する変数を指定します。
'''
''' デリゲートが取得できなかった場合はfalseが返されます。
''' デリゲートが取得できた場合はhandlerにデリゲートが格納されメソッドはtrueを返します。
'''
Public Function GetDelegate(Of T As Class)(ByRef handler As T) As Boolean
Dim dgt As System.Delegate = Me.GetDelegate(GetType(T))
If dgt Is Nothing Then
handler = Nothing
Return False
End If
handler = DirectCast(DirectCast(dgt, Object), T)
Return True
End Function
#End Region
#Region "IDisposable メンバ"
''' Disposeが実行されたかどうか。
Private bDisposed As Boolean = False
''' Disposeメソッドによってすでにリソースが解放されているかどうかを取得します。
Public ReadOnly Property IsDisposed() As Boolean
Get
Return bDisposed
End Get
End Property
''' オブジェクトが破棄されたかどうかを検証し、破棄されている場合はObjectDisposedExceptionを発生させます。
''' retパラメータの型を指定します。
''' オブジェクトが破棄されていない場合にメソッドが返す戻り値を指定します。
''' retパラメータに指定した値がそのまま返されます。
Private Function IfDisposed(Of T)(ret As T) As T
IfDisposed()
Return ret
End Function
''' オブジェクトが破棄されたかどうかを検証し、破棄されている場合はObjectDisposedExceptionを発生させます。
Private Sub IfDisposed()
If IsDisposed Then
Throw New ObjectDisposedException("すでに破棄されたオブジェクトにアクセスされました。")
End If
End Sub
'''
''' 使用されているリソースを解放します。
'''
Public Sub Dispose()
' 重複呼び出し回避
If bDisposed Then
Return
End If
' モジュールを開放
If hModule IntPtr.Zero Then
FreeLibrary(hModule)
End If
bDisposed = True
' 重複呼び出し回避のためのフラグ
End Sub
Private Sub System_IDisposable_Dispose() Implements System.IDisposable.Dispose
Me.Dispose()
End Sub
#End Region
End Class
End Namespace
► スポイラーを表示