前回は、__declspec(dllexport)として外部参照可能な関数として宣言し、GetProcAddressで関数ポインタを取得し、関数を呼び出すことができた・・・。
__declspecは、Microsoft独自の拡張属性構文で属性にはdllexport以外にもいろいろある・・・。
例えば、dllimportを使えば、GetProcAddressによる関数ポインタ取得なしに関数を呼び出すことができる・・・。
__declspec(dllimport) を使ったアプリケーションへのインポート
まず、__declspec_1プロジェクトを作るのだが、
全体のソリューション名を__declspecにしておく・・・。
__declspec_1.cppは、
DllFuncが"DllFunc 1!"と出力するようにしておく・・・。
次に、__declspec_2プロジェクトを追加し、__declspec_2.cppは、
DllFuncが"DllFunc 2!"と出力するようにしておく・・・。
Mainプロジェクトを追加し、Main.cppに呼び出す側の処理を書く・・・。
__declspec(dllimport)で宣言すれば、GetProcAddressなしに呼び出し側から参照できる・・・。
[ビルド]-[構成マネージャ]で、
[新規作成]で新しいビルド構成を作る・・・。
"Release"をベースに、"__declspec_1 Release"という構成を作成・・・。
__declspec_2はビルドしないという構成・・・。
そして、
ここでは[プロジェクト依存関係]で__declspec_1をチェックする・・・。
(__declspec_2はビルドしないのでチェック不要・・・。)
これで、
"__declspec_1 Release"を選択して、ビルド・・・。
Main.exe、__declspec_1.dllができる・・・。
実行すると、
DLL_PROCESS_ATTACH DllFunc 1! DLL_PROCESS_DETACH 続行するには何かキーを押してください . . .
と直接DllFuncを呼び出せる・・・。
同様に、__declspec_2も、
"__declspec_2 Release"という__declspec_1をビルドしない構成を作って、
依存関係も__declspec_2だけチェック・・・。
DLL_PROCESS_ATTACH DllFunc 2! DLL_PROCESS_DETACH 続行するには何かキーを押してください . . .
"DllFunc 2!"が出力された・・・。
さて、この2つのDLLは差し替え可能なのだろうか?
それぞれビルドしている構成も違うので、別々にリンクしてるように感じるかもしれない・・・。
そこで、
出力するDLLのファイル名を、<プロジェクト名>.dllから、
<ソリューション名>.dllに変更・・・。
こうすると、__declspec_1も__declspec_2も、__declspec.dllになる・・・。
両方ビルドした後、__declspec_2 releaseにある__declspec.dllをコピーして、__declspec_1 releaseにある__declspec.dllに上書き・・・。
これで__declspec_1 releaseのMain.exeをコンソールから実行すると、
C:\Project\Cloud\github.com\Sample\winapi\__declspec\__declspec\src\__declspec\__declspec_1 release>Main.exe DLL_PROCESS_ATTACH DllFunc 2! DLL_PROCESS_DETACH C:\Project\Cloud\github.com\Sample\winapi\__declspec\__declspec\src\__declspec\__declspec_1 release>
__declspec_2のDllFuncがちゃんと呼ばれてる・・・。
ということで、ここで生成されたDLLはちゃんと差し替え可能になっている・・・。
Sample/Main.cpp at master · bg1bgst333/Sample · GitHub
Sample/__declspec_1.cpp at master · bg1bgst333/Sample · GitHub
Sample/__declspec_2.cpp at master · bg1bgst333/Sample · GitHub