DLLを作る方法 & 使う方法(単に関数が入っているDLLの場合)
DLLを作る方法 & 使う方法 (単に関数が入っているDLLの場合)
1 新規プロジェクトを選択
2 Win32Dynamic−Link Library を選択する
3 空のDLLプロジェクトを選択する。プロジェクトファイルの名前は仮に「 testdll 」とする
4 ファイル >> 新規作成 >> C/C++ヘッダファイルを選択
ヘッダファイルの内容は以下の通り。変更が必要なのは赤部分のみ。必要な新規ファイルはこれを含めてみっつ。
//-------------------------------------------------------------
// DLL test
//--------------------------------------------------------------
#ifndef _FILTERDLL_H_
#define _FILTERDLL_H_
#ifdef __cplusplus
extern "C" {
#endif
//----------------------------------------------------------
// 外側から呼ぶ関数の宣言
__declspec(dllexport) BOOL APIENTRY GetTestData(DWORD
p);--------------@
__declspec(dllexport) LPCSTR APIENTRY GetTestString(DWORD p);-----------A
#ifdef __cplusplus
}
#endif
5 ファイル >> 新規作成 >> C/C++ソースファイルを選択
ソースファイルの内容は以下の通り
/********************************************************
HTML BannerFilter
*********************************************************/
#include <afx.h>
//----------------------------------------------------------
// 外側から呼ぶ関数本体
BOOL APIENTRY GetTestData(DWORD p, DWORD)-------------------------@
{
int a[]={0,11,22,33,44,55,66,77,88};
if (p<9)
return a[p];
else
return 0;
}
LPCSTR APIENTRY GetTestString(DWORD p, DWORD)----------------------A
{
LPCSTR a = "サンプル文字列NO.2ほいほいXX";
return a;
}
6 ファイル >> 新規作成 >> テキストファイル を選択
ファイル名は、 testdll.def とする。TESTDLL.DEFの内容は以下の通り
LIBRARY testdll
DESCRIPTION 'testdll'
EXETYPE WINDOWS
EXPORTS
GetTestData @1---------------------@
GetTestString @2---------------------A
赤の文字はDLLに含まれる関数、それぞれが対応している。つまり一つの関数をDLLで使うためにはみっつのファイルに定義する必要があるわけだ。おまけにそれがちゃんとかかれていないとDLLにリンクした側が関数を使うことができない。たとえビルドに成功してもちゃんと動かないので、注意しよう。
@は、BOOL変数を返す関数、Aは、文字列を返す関数。
文字列を返す場合はC++の規則になる。このDLLはCの規則を使う約束なので、CStringは使えない。その場合はLPCSTRという文字列型を仕様する。
7 ビルドすると、testdll.dllが出来るので、DLLを使うプロジェクトのデバッグにコピーする(下参照)
8 DLLを使うプロジェクトを開き直してTESTDLLをリンクして関数を呼び出し、ちゃんと動けばOK。
9 自分が使いたい関数をDLLの中に作り、ちゃんと動くかデバッグ。関数の作り方は普通の関数と同じ。ここではAFX.Hをインクルードしているのでクラスを使っても大丈夫。
10 デバッグの場合、DLLを呼ぶ場所にブレークをかけてF11でステップ実行するとDLL内部のコードをトレースすることが出来るので、デバッグも簡単。
10 リリースバージョンはバッジビルドを忘れずに。
DLLの動作チェック
出来たDLLの動作をチェックするためのプロジェクトを作り、動作をチェックする。ここでは仮にプロジェクトの名前をUSEDLLとした。
実行するとDLL内の関数で返した文字列をダイアログで表示したあと、「はいはいはい」と表示されれる。失敗の場合はなが失敗したか表示されるので、それに関係した部分に間違いがないかしらべる。
1 プロジェクトを作る。ダイアログベースでボタンを一つつける。このボタンを押したときにDLL内の関数を呼んで動作を確認するため。
2 ボタンのハンドルに以下のようなコードを入れる。このサンプルにはDLL内の関数を利用する最低限のコードしかかかれていないので、これをカスタマイズすれば自作のDLL関数を使うのに便利かも。
なお、ここでは、ボタンを押すたびにいちいちDLLをリンクして関数を呼んで破棄、というのを繰り返しているが、実際にはアプリが立ち上がったときにDLLをリンクして終わるときに破棄、というのが良いきがする。具体的にはVIEWクラスのコンストラクタでDLLをロードし、デストラクタで破棄という形。DLLハンドラはVIEWクラスのメンバ変数として宣言する。
typedef LPCSTR (APIENTRY *LPGETTESTSTRING_PROC)(DWORD
p,DWORD);---------A
void CUsedllDlg::OnButton1()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
LPGETTESTSTRING_PROC gpGetTestString;
HINSTANCE hInst; // DLLをロードするためのハンドル
hInst = LoadLibrary( "testdll" ); //DLLを読み込みます。
if( hInst == NULL )
{
MessageBox( "DLLをロードできませんでした。" );
return;
}
gpGetTestString = (LPGETTESTSTRING_PROC)GetProcAddress(hInst, "GetTestString");
if( gpGetTestData == NULL )
{
MessageBox( "関数 GetTeastString を取得できませんでした。" );
FreeLibrary( hInst ); //DLLを解放します。
return;
}
LPCSTR hBuff = gpGetTestString(0,0);// コマンド , バッファ(HTML)
MessageBox(hBuff);
MessageBox("はいはいはい" );
FreeLibrary( hInst ); // 使った後は始末する
}