動的なロードは任意のタイミングでDLLの読み込みを破棄を行う方法です。
DLLが存在しなくても、アプリケーションは起動します。
動的なロードでDLLを読み込むには、次の作業を行います。
基本的なDLLの使用方法 DLLを作るで作成したDLLを使用する方法を解説します。
DLLの読み込みには、LoadLibrary()関数を使用します。
HMODULE LoadLibrary(
LPCTSTR lpFileName // モジュールのファイル名
);
引数lpFileNameはDLLのファイル名です。
関数が成功すると、モジュールのハンドルが返ります。
関数が失敗すると、NULL が返ります。
Project1.dllを読み込む処理は次のようになります。
HMODULE dll = LoadLibrary("Project1.dll");
if (dll == NULL)
{
std::puts("DLLの読み込みに失敗しました。");
return 0;
}
DLLの破棄には、FreeLibrary()関数を使用します。
BOOL FreeLibrary(
HMODULE hModule // DLLモジュールのハンドル
);
引数hModuleは、LoadLibrary()関数で取得したモジュールのハンドルです。
関数が成功すると、0以外の値が返ります。
関数が失敗すると、0が返ります。
DLLが持つエクスポート済み関数のアドレスを取得するには、GetProcAddress()関数を使用します。
FARPROC GetProcAddress(
HMODULE hModule, // DLL モジュールのハンドル
LPCSTR lpProcName // 関数名
);
引数hModuleは、LoadLibrary()関数で取得したモジュールのハンドルです。
引数lpProcNameは、関数名です。
関数が成功すると、DLLのエクスポート済み関数のアドレスが返ります。
関数が失敗すると、NULLが返ります
次の関数のアドレスをDLLから取得する方法は、
int WINAPI __declspec(dllexport) Add(int X, int Y);
ソースコードを読みやすくするために、typedefを使って関数型を定義します。
typedef int WINAPI (*TAddProc)(int X, int Y);
関数のアドレスを取得します。
FARPROC proc = GetProcAddress(dll, "Add");
if (proc == NULL)
{
std::puts("関数のアドレスの取得に失敗しました。");
return 0;
}
関数を使用します。
TAddProc add = reinterpret_cast<TAddProc>(proc);
std::cout << add(1, 2) << std::endl;
全体のソースコードは次のようになります。
#pragma hdrstop
#include <tchar.h>
#include <windows.h>
#include <iostream>
typedef int WINAPI (*TAddProc)(int X, int Y);
#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE dll = LoadLibrary("Project1.dll");
if (dll == NULL)
{
std::puts("DLLの読み込みに失敗しました。");
return 0;
}
FARPROC proc = GetProcAddress(dll, "Add");
if (proc == NULL)
{
std::puts("関数のアドレスの取得に失敗しました。");
return 0;
}
TAddProc add = reinterpret_cast<TAddProc>(proc);
std::cout << add(1, 2) << std::endl;
FreeLibrary(dll);
return 0;
}
Borland C++Builder 6実用プログラミング―オブジェクトとその再利用の方法
C++BuilderによるDLL、VCLパッケージ、COM/ActiveXの利用方法が解説されています。
DLLの利用方法についても、Variant配列やSafeArrayを受け渡しする方法やBDEデータベースハンドルを共有する方法など、非常に専門的な内容を取り扱っています。