いつもお世話になっております。
VB2008で開発しています。
C++で作成したネイティブDLLがありまして、
それを使用したいと思っております。
普通に使用する場合は、
以下のようなプログラムで使用できると思います。
Declare Function method Lib "sample.dll" (ByVal a As IntPtr) As Long
Public Sub proc(ByVal hwnd As IntPtr)
Call method(hwnd)
End Sub
ただ今回私がアクセスしたいDLLのファイルのパスが
一定でないため、上記のような相対パスでアクセスできないのです。
"sample.dll"の部分が可変になってしまうのですが、
そこに変数を設定することはできないようで、困ってしまいました。
どのようにして、このDLLファイルにアクセスしたら良いのでしょうか?
大変お手数ではございますが、
もしご存じでしたら、アドバイス頂けませんか?
以上、よろしくお願いいたします。
以下の手順になると思います。
1. LoadLibrary APIでDLLをロードする
2. GetProcAddress APIで関数へのポインタを取得
3. 2.で得た関数へのポインタをSystem.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointerでデリゲートに変換
4. 3.で得たデリゲートを呼び出す
5. 不要になったら,FreeLibrary APIで1.で得たハンドルを解放する
ご回答ありがとうございます。
以下のサイトを参考に1と2の途中まで作ってみました。
http://dobon.net/vb/dotnet/links/extractarchive.html
下にソースを載せておきます。
GetProcAddressの使い方がわかりませんでした。
いろいろ検索してみたのですが、良いページを見付けられませんでした。
「APIの頭に付く文字列」を設定するようなのですが、
この場合であれば何を設定すれば良いのでしょうか?
ご回答ありがとうございました。
以上、よろしくお願いいたします。
Imports System.Runtime.InteropServices
Public Class Form1
'DLLモジュールをマップ
<DllImport("kernel32")> _
Private Shared Function LoadLibrary( _
ByVal lpLibFileName As String) As Integer
End Function
'関数のアドレスを取得
<DllImport("kernel32")> _
Private Shared Function GetProcAddress( _
ByVal hModule As Integer, ByVal lpProcName As String) As Integer
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim dllName As String = "C:\sample.dll"
Dim funcName As String
Dim funcaddr As Integer
'DLLをロード
Dim hmod As Integer = LoadLibrary(dllName)
If hmod = 0 Then
Throw New ApplicationException( _
dllName + "のロードに失敗しました")
End If
'DLLのチェック
'関数のアドレスを取得
funcaddr = GetProcAddress(hmod, funcName + "GetVersion")
If funcaddr = 0 Then
Throw New ApplicationException( _
dllName + "がインストールされていません")
End If
End Sub
End Class
> 「APIの頭に付く文字列」を設定するようなのですが、
何の話でしょうか。
dobonさんのページの説明は,あくまで統合アーカイバプロジェクトのDLLに対しての話です。
MSDNのGetProcAddressのページ
http://msdn.microsoft.com/en-us/library/ms683212.aspx
か,最低でも日本語版のページ
http://msdn.microsoft.com/ja-jp/library/cc429133.aspx
を読んでください。
ご回答ありがとうございました。
以下のサイトも参考にGetProcAddressまでは、
完了できたと思います。
GetProcAddressの引数に設定するのは、関数名だったのですね。
http://www.misuzilla.org/docs/net/dynamic-pinvoke
ただそのあとのデリゲートの処理がうまく理解できませんでした。
デリゲートを定義するところまでは、できたのですが、
GetDelegateForFunctionPointerの第2引数に
返されるデリゲートの型を正しく設定できていないようなのです。
大変お手数ではございますが、
どのように記載したら良いか教えて頂けませんか?
以上、よろしくお願いいたします。
Imports System.Runtime.InteropServices
Public Class Form1
'DLLモジュールをマップ
<DllImport("kernel32")> _
Private Shared Function LoadLibrary( _
ByVal lpLibFileName As String) As Integer
End Function
'関数のアドレスを取得
<DllImport("kernel32")> _
Private Shared Function GetProcAddress( _
ByVal hModule As Integer, ByVal lpProcName As String) As Integer
End Function
Delegate Sub SampleMethod(ByVal a As Integer)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim dllName As String = "C:\Sample.dll"
Dim funcName As String = "SampleMethod"
Dim funcaddr As Integer
'DLLをロード
Dim hmod As Integer = LoadLibrary(dllName)
'関数のアドレスを取得
funcaddr = GetProcAddress(hmod, funcName)
Dim method As SampleMethod
method = Marshal.GetDelegateForFunctionPointer(funcaddr, SampleMethod)
End Sub
End Class
GetDelegateForFunctionPointerメソッドの第2引数はデリゲート型を表すSystem.Typeオブジェクトです。
GetType演算子を使って,デリゲート型のTypeオブジェクトを取得してください。
http://msdn.microsoft.com/ja-jp/library/tay4kywk.aspx
ありがとうございました。
無事解決できました。
返信が遅くなってしまい、申し訳ございません。
とても助かりました。