DLLファイルのパスが固定でないネイティブDLLを使用したい

解決


レン  2009-03-02 21:18:37  No: 141599

いつもお世話になっております。

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ファイルにアクセスしたら良いのでしょうか?
大変お手数ではございますが、
もしご存じでしたら、アドバイス頂けませんか?

以上、よろしくお願いいたします。


YuO  2009-03-02 21:49:24  No: 141600

以下の手順になると思います。
1. LoadLibrary APIでDLLをロードする
2. GetProcAddress APIで関数へのポインタを取得
3. 2.で得た関数へのポインタをSystem.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointerでデリゲートに変換
4. 3.で得たデリゲートを呼び出す
5. 不要になったら,FreeLibrary APIで1.で得たハンドルを解放する


レン  2009-03-04 03:44:58  No: 141601

ご回答ありがとうございます。

以下のサイトを参考に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


YuO  2009-03-04 05:29:15  No: 141602

> 「APIの頭に付く文字列」を設定するようなのですが、

何の話でしょうか。
dobonさんのページの説明は,あくまで統合アーカイバプロジェクトのDLLに対しての話です。

MSDNのGetProcAddressのページ
http://msdn.microsoft.com/en-us/library/ms683212.aspx
か,最低でも日本語版のページ
http://msdn.microsoft.com/ja-jp/library/cc429133.aspx
を読んでください。


レン  2009-03-04 18:43:16  No: 141603

ご回答ありがとうございました。

以下のサイトも参考に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


YuO  2009-03-05 01:46:42  No: 141604

GetDelegateForFunctionPointerメソッドの第2引数はデリゲート型を表すSystem.Typeオブジェクトです。
GetType演算子を使って,デリゲート型のTypeオブジェクトを取得してください。
http://msdn.microsoft.com/ja-jp/library/tay4kywk.aspx


レン  2009-03-11 18:16:30  No: 141605

ありがとうございました。
無事解決できました。
返信が遅くなってしまい、申し訳ございません。
とても助かりました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加