#DLLとは
DLL(ダイナミックリンクライブラリ)は動的割り付けがされるライブラリ
- exeファイルの容量が小さくなる
- アップデートするときはDLLを更新してインストールすればよい.(実行ファイルの再コンパイルは不要)
と,メリットが大きいです.そこでDLLを1から作ります.
#C++でDLLの作成
- DLLのひな型を作成
- DLLで提供する関数の作成
- 関数作成時の注意点,小技
新規プロジェクト作成
VisualStudioで新規プロジェクト作成から言語をC++にしてダイナミックリンクライブラリを選択すると,DLLのひな型が出来上がります.
そうするとDLLのmain関数にあたるものが作成されます.
#include "pch.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
##メソッドの作成
DLLで提供する関数は先頭に__declspec(dllexport)
をつけて,それを利用する側は__declspec(dllimport)
を先頭につけるのが原則です.
ただ利用する側がdllexportをdllimportに毎回書き換えるのは面倒なので,マクロを定義するのが一般的です.
作成側はプロジェクトのプロパティから「C/C++>プリプロセッサの定義」へ行き,PRODUCT_EXPORTSを定義します.
そうすると作成側のマクロではPRODUCT_APIがdllexportとなります.
利用する側はPRODUCT_EXPORTSを定義せずに使うのでPRODUCT_APIはdllimportに切り替わります.
#ifdef PRODUCT_EXPORTS
#define PRODUCT_API __declspec(dllexport)
#else
#define PRODUCT_API __declspec(dllimport)
#endif
class PRODUCT_API Product
{
public:
unsigned long OpenDevice(HANDLE handle);
};
PRODUCT_API unsigned long OpenDevice(HANDLE handle);
関数作成時の注意点
extern cをつける
C++コンパイラではマングリングと呼ばれる処理を行なっています.C++は関数のオーバーライドや名前空間を使って同じ名前の関数でも違う機能を与えることがでるので,それらの区別がつくようにコンパイラで関数のシンボルに文字を付け加えています.
これがDLLをC言語で使う場合に邪魔になるので関数にはextern "C"
を付けます.
// 関数のプロトタイプ宣言はextern "C"の中
#ifdef __cplusplus
extern "C"
{
#endif
PRODUCT_API unsigned long OpenDevice(HANDLE handle);
#ifdef __cplusplus
}
#endif
型を自動でOSに合わせる
HANDLE型はOSのメモリによってサイズが異なり,x86では32ビット, x64では64ビットとなります.プラットフォームに応じて容易に切り替えられるようにハンドルの型をマクロで定義します.
x64にしてビルドする際には_M_X64Xというマクロが定義されるのでそれを利用しますコンパイルされます.
#ifdef _M_X64
#define COM_HANDLE unsigned long long
#else
#define COM_HANDLE unsigned long
#endif