Tips of VC++ > DLL > 暗黙的リンク
前へ戻る次へ進む


このドキュメントにはサンプルプログラムが含まれています。
ワークスペース
ソースファイル(テキスト)


暗黙的リンク

最初に「DLL概要」「エクスポートとインポートとリンク」を 読むと、すんなりと理解できるでしょう。 はっきりした理由がない限り、リンク方法には暗黙的リンクをお薦めします。 ただし、この方法を使うときは以下のファイルが必要になってきます。

これだけのファイルが揃っていれば、あとは手順どおりです。 ヘッダーをインクルード、インポートライブラリとリンク、関数呼び出し。 ハイ、終了〜。簡単ですね。MSDNでも同じことが書いてあります。

DLL を使う実行形式は、各ソース ファイル内のエクスポート関数 (または C++ クラス) を含むヘッダー ファイルをインクルードする必要があります。各ソース ファイルには、エクスポート関数の呼び出しが含まれています。コーディングの面から見ると、エクスポート関数の関数呼び出しは、その他の関数呼び出しとほとんど同じです。

実行可能ファイルの呼び出しをビルドするには、インポート ライブラリとリンクする必要があります。外部メイクファイルを使う場合は、リンクするその他のオブジェクト ファイル (.OBJ) やライブラリを列記したインポート ライブラリのファイル名を指定します。Visual C++ の開発環境で作業する場合は、[プロジェクトの設定] ダイアログ ボックスの [リンク] タブの [オブジェクト/ライブラリ モジュール] ボックスに、インポート ライブラリ名を指定します。

このへんで蛇足を一つ。別に飛ばしてもけっこうです。(主にMSDNの翻訳)

暗黙的リンクの仕組み

まずDLLを使用するアプリケーションをビルドしたときに何が起こるのでしょう? DLL関数を呼び出す実行形式のソースコードをコンパイルすると、 オブジェクトコード内に外部関数への参照が生成されます。 このとき、関数の定義はもちろん存在しないので、そのままコンパイルすると 外部参照が未解決でなんちゃらかんちゃらと言う お馴染みの(笑)エラーが出るはずです。 そこでアプリケーションをインポートライブラリファイルと リンクする必要が生じるのです。

インポートライブラリには、DLLをロードし、DLL内の関数呼び出しを インプリメントするコードが含まれているだけです。 リンカは、インポートライブラリ内に外部関数を見つけると、 その関数のコードはDLL内にあるものと認識します。 リンカは、単にDLLコードの場所を実行可能ファイルに記入することによって、 外部参照を解決します。システムはプロセスの起動時にこの情報を利用します。

プログラムが起動されるとまず、DLLをロードし、 モジュールがプロセスのアドレス空間にマップされます。 そして、エントリポイント関数(初期化および終了コード用)を呼び出します。 これがDllMain関数ですね。 このときのパラメータの1つは、DLLがプロセスにアタッチされようと していることを示すコードになります。

その後、システムはプロセスの実行可能コードを変更し、 そのDLL関数の開始アドレスをセットします。 これでDLL関数はアプリケーション自身の関数と同じように扱われるのです。

サンプルを作ってみます。 「__declspec(dllexport)を使ってエクスポート」 で作ったDLLを使用します。

作業フォルダに適当なフォルダを作り、 ヘッダーとインポートライブラリをコピーします。 DLL本体はdebugフォルダとかreleaseフォルダにいれてください。 実行ファイルと同じディレクトリに入れないとエラーが出ます。

まず、ヘッダーをインクルードします。 "stdafx.h"に追加するのが一般的ですね。

次にインポートライブラリをリンクするようにします。 [プロジェクト]-[設定]-[リンク]-[オブジェクト/ライブラリ モジュール]に パスを追加してください。

これで下準備は完了です。 あとはひたすら関数を使う。使う!使う!! サンプルのDLLに含まれていた関数はaverageでしたね。 こんな感じでしょうか。

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow )
{
    int n= average(32,56);

    char buf[10];
    ::wsprintf(buf,"%d",n);
    ::MessageBox(NULL,buf,"DLLのてすと",MB_OK);

    return 0;
}

無駄にダイアログを表示させてみました。 44と表示されるはずです。

Jul. 2, 2002