DLLの明示的リンク用typedefの正しい書き方
DLLには暗黙的リンクと明示的リンクの2種類の利用方法がある。
コーディングの立場からすると暗黙的リンクが断然楽なのだが、リンクの遅延が出来ないために明示的リンクを利用せざるを得ないことが多い。
明示的リンクを利用する場合、::GetProcAddress() によって関数ポインタを取得し、それをあらかじめtypedefしておいた関数ポインタ型のポインタ変数に代入して使用するのが一般的である。
呼び出し側
typedef int (*P_someFunction)(int param1, char* str1);
P_someFunction someFunction = (P_someFunction)::GetProcAddress(handle, "someFunction");
int ret = someFunction(2, "message");
呼び出され側
#define DLL_EXPORT extern "C" __declspec(dllexport)
DLL_EXPORT int someFunction(int param1, char* str1){
//なんか処理
return 0;
}
しかしここで、someFunctionの定義が分離してしまうのがどうにも気に食わない。
ましてDLL呼び出し時にパラメータの型が間違っていたらスタックがおかしくなって解決困難なバグに発展することは目に見えている。
暗黙的リンクを用いる場合は、共通のヘッダをifdefで切り替えてやることでこの問題を解決しているのだが、明示的リンクの場合には同じ方法が使えない。
遅延リンクを使いたいだけなのに、なぜこんな苦労をせねばならんのだ。
ということで、考えました。以下がソース。
共通ヘッダ
// typedefはポインタじゃなくする
typedef int (def_someFunction)(int param1, char* str1);
呼び出し側
def_someFunction* someFunction = (def_someFunction*)::GetProcAddress(handle, "someFunction");
int ret = someFunction(2, "message");
呼び出され側
#define DLL_EXPORT extern "C" __declspec(dllexport)
// アヤシイ記法だが、プロトタイプ宣言として通る
DLL_EXPORT def_someFunction someFunction;
//ここまでヘッダ
DLL_EXPORT int someFunction(int param1, char* str1){
//なんか処理
return 0;
}
ソースコードの量は増えているが、呼び出し側と呼び出され側で共通のプロトタイプを参照しているので、コンパイル時に型チェックをすることが出来る。
もっと良い方法があるなら誰か教えてください。
ちなみに新規開発ならこっちのほうが断然カッコイイ。
DLL の中のC++クラスの安全なエクスポート
のだが、実はけっこう表記ミスとか多いので、改めてここに書こうと思う。
今日になって、/DELAYLOAD というのを知った。なんだこれ超便利じゃん。