目次
英語版
このページの英語版を見る
Windows DLLの作成
DLLをビルドする
DLL用のコード
- mydll
- .
- dファイルを作成する
- :
module mydll; import core.sys.windows.dll; import core.stdc.stdio; mixin SimpleDllMain; export void entry() { printf("called mydll.entry()\n"); }
- DLLをコンパイルおよびリンクする :
dmd -shared mydll
- これにより、mydll.lib (インポートライブラリ)とmydll.dll (dll)のファイルが作成される 。
- mydll.diファイルを作成する :
module mydll; export void entry();
- mydll.diファイルを作成する :
module myexe; import mydll; int main() { mydll.entry(); return 0; }
- myexe.d ファイルをコンパイルし、mydll.libファイルとリンクしてmyexe.exe ファイルを作成する:
dmd myexe.d mydll.lib
- myexe
- を実行する :
C:> myexe called mydll.entry()
DllMain
-エントリーポイント Windows DLLには
、実行可能ファイルのmain 関数と同様に、エントリーポイントが必要である。 以下のような形になる。module dllmain; // 常にこの名前を付けておくといい import core.sys.windows.windef : HINSTANCE, BOOL, DWORD, LPVOID; import core.sys.windows.winnt; import core.sys.windows.dll : dll_process_attach, dll_process_detach, dll_thread_attach, dll_thread_detach; __gshared HINSTANCE g_hInst; // DLLのインスタンスハンドルを保存する /*********************************** * DLLのエントリーポイント。 * Params: * hInstance = DLLのインスタンスハンドル * ulReason = なぜDllMainが呼び出されるのか * fImpLoad = Dllが明示的にロードされた場合はnull、暗黙的にロードされた場合は!null * Returns: * 成功ならtrue、失敗ならfalse */ extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID fImpLoad) { switch (ulReason) { case DLL_PROCESS_ATTACH: // DLLが最初にロードされたとき g_hInst = hInstance; // 後で使うために保存しておく return dll_process_attach(hInstance, true); // プロセスに関連した初期化を行う case DLL_PROCESS_DETACH: // DLLがアンロードされるとき return dll_process_detach(hInstance, true); // プロセス相対ティアダウンを実行する case DLL_THREAD_ATTACH: // 新しいスレッドの初期化を行う return dll_thread_attach(true, true); // スレッド相対初期化を実行する case DLL_THREAD_DETACH: // スレッドが終了する return dll_thread_detach(true, true); // スレッドのティアダウンを実行する default: assert(0); } }あるいは、これは単なる定型コードなので、以下のようにしてもよい。
module dllmain; import core.sys.windows.dll; mixin SimpleDllMain;コンパイラはDllMain を認識し、__acrtused_dll への参照を発行する。これにより、 CランタイムライブラリからDLLサポートコードが取り込まれる。また、 デバッグランタイムライブラリ (シンボリックデバッグコンパイル用)またはデフォルトランタイムライブラリ(それ以外の場合)が リンカーによって検索される。
定義のエクスポート
実行可能ファイルがDLL内の名前を参照できるようにするには
、その名前がDLLによってエクスポートされていなければならない。 例えば、このモジュールからシンボルfunc をエクスポートするには、module mydll; export int func() { return 3; }コンパイラはオブジェクトファイルに以下のエクスポート定義指令を挿入する。
EXPDEF expflag=x00, export '__D5mydll4funcFZi', internal '', ordinal=x0OMFファイル用、およびMSCOFFオブジェクトファイル用の同等物。EXPDEF は、mydll.func がリンクされるDLLのエクスポートテーブルに置かれるべきであることをリンカーに通知する。 オブジェクトファイルへの追加はこれだけである。
宣言のインポート EXEファイル
にDLLが添付される場合、EXEファイル
はDLLを呼び出す方法を知っておく必要がある。これは DLLからの宣言のインポートと呼ばれる。インポートファイルを用意するmydll.di :module mydll; export int func(); // 関数本体がないことに注意する
module myexe; import mydll; int test() { return func(); }myexe.d をコンパイルすると、マジックが明らかになる。
extrn __imp___D5mydll4funcFZi __D5myexe4testFZi comdat call dword ptr __imp___D5mydll4funcFZi retmydll.func() への直接呼び出しは行われず、代わりにmydll.func() への間接呼び出しがmydll.func() へのポインタを介して行われ、そのポインタの名前は__imp___D5mydll4func である
ライブラリをインポートする
dllのオブジェクトファイルから定義をエクスポートし、exeファイルをdllのエクスポートにフックするには、 追加のファイルであるインポートライブラリが必要となる。インポートライブラリは dllがリンクされた際にリンカーによって自動的に作成される。このライブラリは、 実行可能ファイルをリンクする際にリンクステップに追加する必要がある。
参考文献
Copyright © 1999-2024 by the D Language Foundation
DEEPL APIにより翻訳、ところどころ修正。
このページの最新版(英語)
このページの原文(英語)
翻訳時のdmdのバージョン: 2.109.1
ドキュメントのdmdのバージョン: 2.109.1
翻訳日付 :
HTML生成日時:
編集者: dokutoku