Version 15.18
一から作った DLL を使ってみる
「前回は、一から DLL を作ってみました」
『そんなに難しくなかったよーな』
「押さえなきゃいけないのはこの3つだけ」
・DllMain() を作る
・インポート・エクスポートの切り替えシステムを作る
・エクスポートする関数を作る
「しかも最初の2つは、どんな DLL でも流用できるから」
『一度作っちゃえば特に問題なし、ってことね。最後の関数も、結局関数の
前に、 DLLTESTHARD_API とか付ければいいだけだし』
「そうだね、切り替えシステムのマクロを付ければいいだけ。クラスもそ
う」
『作ってないけど、クラスの方が簡単だよね』
「だね、関数は全部の関数の前に付けなきゃいけないけど、
Version 15.16 ( No.316 ) で説明したとおり、クラスならクラス単位で付
ければいいだけだから」
『だね』
「さて、じゃあ前回作った DLL を使ってみます」
『おー』
「まず、 BuildTest プロジェクトの Debug フォルダに DLLTestHard.dll
をコピーして」
『ほい。なんか DLL ふたつになっちゃったけど』
「気になるなら DLLTestEasy.dll の方は削除してもいいから」
『はーい』
「この DLL のコピーって忘れやすいから注意してね」
『ってゆーか、ビルドするたびにコピーっていうのも結構面倒……』
「これ、自動化する方法あるよ」
『え、そうなの!?』
「メニューの【プロジェクト】-【設定】ダイアログ開いて」
『いつものね』
「右端のページに【ビルド後の処理】ってあるでしょ」
『あ、ある』
「この【ビルド後の処理コマンド】ってところに、したい処理を書くと、
ビルドを実行した後に自動的に実行してくれるんです」
『……したい処理、って、処理って何? 何書けばいいの?』
「あー、 DOS のコマンドとか」
『 DOS のコマンドなんて知らない……』
「だね……たとえば、 DLL のコピーは、こういうコマンドになります」
copy D:\DLLTestHard\Debug\DLLTestHard.dll D:\BuildTest\Debug
「あ、フォルダ構成が以下の場合の話だからね」
・DLLTestHard : D:\DLLTestHard
・BuildTest : D:\BuildTest
『へー、これでファイルのコピーができるんだ』
「先の事を考えると、こういう事もできた方がいいんだけど……」
『こういうコマンド知ってないといけないの?』
「 Windows はいいんだけど、他の OS 、特に UNIX 系だとね」
『そうなんだ……』
「まぁとりあえずはいいから、こういうふうに copy コマンドでファイルの
コピーができるから、これを使えば……ビルドしてみて」
『あ、はい。ビルド……あ』
--------------------構成: DLLTestHard - Win32 Debug-----------------
コンパイル中...
Func.cpp
リンク中...
1 個のファイルをコピーしました。
DLLTestHard.dll - エラー 0、警告 0
『コピーされた!』
「こうすれば、ビルド後に DLLTestHard.dll をコピーしてくれるから楽」
『うん、楽!』
「さて、 DLL をコピーしたら、これを使ってみます。 BuildTest
プロジェクトを開いて」
『ほい』
「次に、インクルードファイルのパスの設定をします」
『いくつかあるよね、方法』
「だね、まずはひとつは、【設定】ダイアログで、インクルードファイルの
あるフォルダを設定する方法」
『えっと、メニューの【プロジェクト】-【設定】ダイアログの、【C/C++】
ページの【プリプロセッサ】ページの、【インクルード ファイルのパス】
に DLLTestHard プロジェクトのフォルダのフルパスを書く、だよね』
「正確には DLLTestHard.h とかのヘッダーファイルの置いてあるフォルダ
のフルパス、ね」
『はーい』
「他には?」
『えっと、 Version 15.08 ( No.308 ) でやった、【オプション】
ダイアログの【ディレクトリ】のページの【インクルードファイル】のとこ
に設定する、っていうの』
「そうそう。この方法だと、他のプロジェクトでも共通して使えるから、
そういう共通で使うライブラリはここで登録した方がいいかな」
『なんかそういう DLL 作れるとちょっとかっこいいかも……』
「あと、あとでヘッダーファイルをインクルードするけど、その時に
ヘッダーファイルをフルパスで指定する、って方法もあるかな」
『げ、それかっこよくない』
「だね、まぁ普通はしないかな。だから、ヘッダーファイルの置いてある
フォルダの指定方法は、以下の2つ」
・【設定】ダイアログで指定する
・【オプション】ダイアログで指定する
「この2つのうちどちらかをすれば、インクルードファイルが見られるよう
になるから」
『次はライブラリファイルね』
「そう。インクルードファイルとほとんど同じだけどね」
『えと、【設定】ダイアログの【リンク】ページの【インプット】ページの
【追加ライブラリのパス】に DLLTestHard.lib が置いてあるフォルダの
フルパスを書いて、と』
「これで、ライブラリファイルが見られるようになります」
『これしなくても、さっきと同じように【オプション】ダイアログの
【ディレクトリ】ページで【ライブラリ ファイル】にそのフォルダを
書いてもいいんだよね』
「そう。だから、ライブラリファイルの置いてあるフォルダの指定方法は、
こちらも次の2つ」
・【設定】ダイアログで指定する
・【オプション】ダイアログで指定する
『こっちも、フルパスで指定する、っていうのもあり?』
「一応ね。で、ライブラリファイルの方は、置いてあるフォルダだけじゃな
くて、ファイルも指定しないと」
『そだった。えっと、【設定】ダイアログの、【リンク】ページの【一般】
ページの、【オブジェクト/ライブラリ モジュール】に DLLTestHard.lib
を書いて、と』
「そうそう、それで DLLTestHard.lib が参照されます」
『これは他に方法あるんだっけ』
「あるよ、 #pragma comment() を使う方法」
『あ、それもさっきの Version 15.08 ( No.308 ) で教わったね』
「だから、ライブラリファイルの指定方法は次の2つの方法があります」
・【設定】ダイアログで指定する
・#pragma comment() で指定する
『どっちの方がいいの?』
「場合によるかな。 #pragma comment() で指定するなら、【設定】
ダイアログで指定してるのも全部 #pragma comment() で指定した方がいい
かも」
『統一しろってことね』
「 MFC は #pragma comment() の方だから、 MFC の方は #pragma
comment() で統一した方がいいかも」
『そういえば MFC は【設定】ダイアログの方じゃ全然やってないんだもん
ね』
「さて、ここまでで準備ができました。準備に必要だったことは以下の通
り」
・DLL をコピーする
・インクルードファイルのあるフォルダを指定する
・ライブラリファイルのあるフォルダを指定する
・ライブラリファイルを指定する
『全部終わったけど、意外と面倒だよね』
「まぁ、使う DLL はそうそう増えたりしないだろうから」
『確かに……』
「以上が完了したら、実際にプログラムの方で呼び出します。 Main.cpp
を開いて、以下のように修正してください」
// Main.cpp
#include <Windows.h>
#include "DLLTestHard.h"
#include "Func.h"
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
Output( "あいうえお\n" );
return 0;
}
「ポイントはふたつ。ひとつはヘッダーファイルのインクルード」
#include "DLLTestHard.h"
#include "Func.h"
「両方とも DLLTestHard のヘッダーファイル。順番間違えちゃ駄目だから
ね」
『え? なんで?』
「 DLLTestHard.h には何書いてあったっけ?」
『えっと……あ、インポートとエクスポートを切り替えるマクロ』
「でしょ。このヘッダーファイルでまずそのマクロを読み込んで」
『関数本体のある Func.h でそれを使う……だから順番が重要』
「そういうこと。ま、逆にしてもコンパイルエラーになるけど」
『ホントだ』
「あとは、使うだけ」
Output( "あいうえお\n" );
「関数の呼び出しは普通にできるから」
『だよね、 API だって普通に呼び出せるんだし』
「そういうこと。準備は大変だったけど、ここまでやれば、 DLL の関数も
普通の関数と同じように呼び出せるから」
/*
Preview Next Story!
*/
『これで DLL を簡単に使えそう』
「そうなってくるとクラスや関数を DLL に出したくなるから」
『……でもそれってデバッグとかできないから大変そう』
「そんなことないよ、ちゃんとデバッグする方法があるんです」
『え、そなの?』
「というわけで次回」
< Version 15.19 DLL をデバッグ! >
『につづく!』
「すっごく簡単だから、 DLL のデバッグ」
『いや、信じられないし』