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 ); // 使った後は始末する
 
}