QA@IT

Dll 内の関数を別の Dll を使って呼び出したい。

4181 PV

ある Dll( Dll_A とします) 内にある関数( foo とします)を別の Dll( Dll_B とします) から呼び出したいのですが、どうすれば宜しいでしょうか?

初めまして。 mickySan と申します。

早速で恐縮ですが、質問させて頂きます。

Dll_A 内にある関数は declare 関数を使って、以下のようにして呼び出せました。

'標準モジュール内
  Declare Function foo Lib "Dll_A.dll" _
     (ByRef val1 As Any, ByVal val2 As Long, _
      ByVal val3 As Long, ByVal val4 As Long, _
      ByRef val5 As Any) As Long

'フォーム内
    return = foo(val1, val2, val3, val5, val6)

ここで、別の Dll を介して Dll_A を呼び出したいという要望を受け、VB6 の ActiveX Dll から Dll_B を作成しました。
DLL_B の中身は以下の通りです。(海外の情報を参考にしました)

Option Explicit

Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal mParam As Long) As Long

Private Function bar(val1 As Long, val2 As Long, val3 As Long, val4 As Long, val5 As Long)
On Error Resume Next
'We're going to call an API-function, without declaring it!
Dim lb As Long, pa As Long
'map 'user32' into the address space of the calling process.
lb = LoadLibrary("Dll_A")
'retrieve the address of 'SetWindowTextA'
pa = GetProcAddress(lb, "foo")
'Call the SetWindowTextA-function
CallWindowProc pa, ByVal val1, ByVal val2, ByVal val3, ByVal val4, ByVal val5
'unmap the library's address
FreeLibrary lb
End Function
'参考にしたコードここから
Create a New project And add this code To Form1
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Any, ByVal wParam As Any, ByVal lParam As Any) As Long

Private Sub Form_Load()
On Error Resume Next
'We're going to call an API-function, without declaring it!
Dim lb As Long, pa As Long
'map 'user32' into the address space of the calling process.
lb = LoadLibrary("user32")
'retrieve the address of 'SetWindowTextA'
pa = GetProcAddress(lb, "SetWindowTextA")
'Call the SetWindowTextA-function
CallWindowProc pa, Me.hWnd, "Hello !", ByVal 0&, ByVal 0&
'unmap the library's address
FreeLibrary lb
End Sub
'参考にしたコードここまで

これを実行して作成した Dll_B を冒頭と同じように declare 関数を使って、以下のようにして呼び出しました。

'標準モジュール内
  Declare Function bar Lib "Dll_B.dll" _
     (ByRef val1 As Any, ByVal val2 As Long, _
      ByVal val3 As Long, ByVal val4 As Long, _
      ByRef val5 As Any) As Long

'フォーム内
    return = bar(val1, val2, val3, val4, val5)

しかし、いざコードを走らせると、
「実行時エラー'453': エントリ bar が DLL ファイル Dll_B 内に見つかりません。」
と出てしまいます。

コマンドプロンプトから DLL_B のレジストリ登録を済ませてもエラーは相変わらず表示されます。

(環境: Windows 7 Professional / Microsoft Visual Basic 6.0)

解決策はありますでしょうか?
お忙しいところ恐縮ですが、諸先輩方の知恵をお借り出来れば幸いです。

宜しくお願い致します。

回答

コードの方はあまり見ていませんが、VB6でActiveXプロジェクトで作ってregsvr32で登録した
ならCreateObjectで生成すればいいと思います。

ちょっと細かいところまで覚えてないですがプロジェクト名.クラス名で CreateObjectしてメソッド呼べばよかったような。

ActiveX プロジェクトのプロジェクト名が Project1で
クラス名がClass1 なら

Dim objB As Object
set objB = CreateObject("Project1.Class1")
call objB.bar()
set objB = Nothing

こんな感じで呼べると思うんですが、随分前に触ったきりなので間違ってたらすいません。

DLLにもいろいろあるので、どのタイプかによって呼び出し方も違います。
DLL_BからDLL_Aを呼ぶのはDLL_B作る前と同じ様にDeclare Functionでいいと思います。


別途気になるのですが、オーダーとしてDLLを介してDLL_Aを呼びたいといわれている点なのですが、
老婆心ながらその意図を確認した方が良いように思います。
(何から呼びたくてDLLを挟んでほしいとオーダーされているのか、単純にはActiveX DLLでよいのか(はたまたCのDLLとか.NETのDLLが良いということはないか)。)
既に意図を把握なされている場合(またはActiveX DLLで良いと言われている場合)は無視してください。

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。