#pragma twice

KAB-studio > プログラミング > #pragma twice > 317 Version 15.17 一から DLL を作ってみる

#pragma twice 317 Version 15.17 一から DLL を作ってみる

前のページへ 表紙・目次へ 次のページへ

 Version 15.17
一から DLL を作ってみる

ここまで、関数とクラスを DLL の中で作って使ってみる、というのをし
てみました
うん、結局 __declspec(dllexport) 使えば簡単だったなーと
……本当に簡単?
え?
ここまで見てきたのって、 Version 15.09 ( No.309 ) で作った DLL で
試してきたけど
あー、そういえばあの時作った DLL って、 AppWizard がほとんど全部用
意してくれてたんだよね……もしかして?
そう、それを一から自分で作ってみましょう
やっぱり……
というわけで、まずは新しいプロジェクトから作ります
メニューの【新規作成】、【プロジェクト】のページで左は
【Win32 Dynamic-Link Library】、右のプロジェクト名は DLLTestHard 、

 Hard ……まぁいいけど
心意気よ心意気。で、

・空の DLL プロジェクト
・単純な DLL プロジェクト
・シンボルをエクスポートする DLL

やっぱ一番上?
そ、一番上
やっぱり……ん、プロジェクトできたよ。見事に何もないけど
大丈夫大丈夫、ひとつひとつ作っていけばいいから。まず、 DLL になく
てはならないもの、それは?
なくてはならないもの? なんかあったっけ
じゃあ普通のプログラムだと絶対にあるものは?
んー、 WinMain() はあるよね……あ! DllMain() だ!
そういうこと。普段使わないからあんまり気にならないけど必要だから
使わないのに必要っていうのもね……
まずは DllMain() を作ります。メニューの【ファイル】-【新規作成】で
【ファイル】のページを表示して、左は【C++ ソース ファイル】、右の
【ファイル名】は DLLTestHard.cpp 
これってプロジェクト名じゃなきゃだめ?
そんなことないよ。 DLL も Exe も、基本的にソースファイル名や
ヘッダーファイル名に制限はないから。 MFC はプロジェクト名を元に
ファイル名を作ることが多いけど
じゃあ普通はどうするの?
いろんなプロジェクトで使う場合は Main.cpp とかのシンプルな名前の方
が多いかも。特にクラスがなくて関数ばかりの時とかは
そうなんだ
ま、プロジェクト名の方が分かりやすいけどね
じゃ、 DLLTestHard.cpp で。空のファイルできた
そこに DllMain() を作ります

// DLLTestHard.cpp

#include <windows.h>

BOOL APIENTRY DllMain
    ( HANDLE hModule
    , DWORD  ul_reason_for_call
    , LPVOID lpReserved
    )
{
    return TRUE;
}

……中見ないから本当に必要性なさそうだね……
ただ
ただ?
 DLLTestEasy の例を見てもらうと分かるんだけど、 DLL って、関数や
クラスだけじゃなくて、変数もエクスポートできるんです
あ、そういえばあったね
そういう場合、 DllMain() で初期化処理することになるから
なんで変数の使い方、説明しなかったの?
基本的には関数と同じ方法でエクスポートできるし、それに、 DLL の
変数って、完全なグローバル変数だから
 Version 6.16 ( No.116 ) で言ってたね、グローバル変数は作っちゃ
駄目だって
そう、ましてや DLL なんかに置いてあったら、いろんなアプリからアク
セスし放題だもの。管理なんて全然できないから
確かに……
だから基本的に、作らないし使わないってことで
だから DllMain() も使い道がない、と
そういうことになるね。さて、これで DLL を作るのに最低限必要なもの
ができたので、ビルドしてみて
ほい、成功した。 DLLTestHard.dll できたよ。なんにもエクスポートし
てないからライブラリファイルはないけど
ではエクスポートしましょう。まずは __declspec の切り替えシステムを
用意します
あ! そっか、それ作らなきゃいけないんだ
というわけで、インポート・エクスポートのための切り替えシステムを作
ります。メニューの【ファイル】-【新規作成】で【ファイル】のページを
表示して、左は【C/C++ ヘッダー ファイル】、右の【ファイル名】は 
DLLTestHard.h 
空のファイルできた
そこにこう書き込んで

// DLLTestHard.h

#ifdef DLLTESTHARD_EXPORTS
    #define DLLTESTHARD_API __declspec(dllexport)
#else
    #define DLLTESTHARD_API __declspec(dllimport)
#endif

 DLLTESTHARD_EXPORTS が #define されていたら、DLLTESTHARD_API は 
__declspec(dllexport) に置き換わって、エクスポートされる。されていな
かったら、 DLLTESTHARD_API は __declspec(dllimport) に置き換わって
インポートされる、ね
そういうこと
この DLLTESTHARD_EXPORTS とか DLLTESTHARD_API とかも好きな名前で
いいの?
うん、プロジェクト名とかとは関係ないから。ただ、他の DLL とかと被
るとまずいかな
他と同じじゃダメってことね
それに、プロジェクト名を使った方が楽だよ
楽?
メニューの【プロジェクト】-【設定】ダイアログの、【C/C++】ページの
【一般】ページの、【プリプロセッサの定義】見てみて
ん……あーっ!!

WIN32,_DEBUG,_WINDOWS,_MBCS,_USRDLL,DLLTESTHARD_EXPORTS

 DLLTESTHARD_EXPORTS が、ある!!
そう、実は AppWizard が、この名前で追加してくれてるんです。ここで
書かれている文字列は

#define DLLTESTHARD_EXPORTS

と同じ意味だから
自動的にエクスポートされる……ちょっとビックリ……
だからプロジェクト名を元に付けた方が、ちょっとだけ楽になるかな。さ
て、これでエクスポートとインポートの準備ができました。さっそく
エクスポートする関数を作ってみましょう
はーい
さっきの DLLTestHard.cpp と同じ方法で、 Func.cpp ってファイルを
作って
あれ? 別ファイルにするの?
普通はその方がいいかな。 DLLTestHard.cpp と別にすることで、外から
呼ばれる関数ってことが分かりやすいし
なんかちょっと面倒だけど……ん、 Func.cpp 作ったよ
じゃ、こんなふうにして

// Func.cpp

#include <windows.h>
#include "DLLTestHard.h"
#include "Func.h"

// エクスポートする関数。
DLLTESTHARD_API void Output( const char *p_pch )
{
    OutputDebugString( p_pch );
}

文字列受け取って出力する関数ね
エクスポートするのから先頭に DLLTESTHARD_API を付けています。では
次に、同じように Func.h を作って
ほい
そうしたらこんな感じに

// Func.h

DLLTESTHARD_API void Output( const char *p_pch );

つか Func.cpp のをそのまま貼り付ける感じね
うん、それでいいよ。これでビルドして
ビルド! うん、 DLLTestHard.dll も DLLTestHard.lib もできた
以上で、関数をエクスポートする DLL ができました
あ、結構簡単かも
要は

・DllMain() を作る
・インポート・エクスポートの切り替えシステムを作る
・エクスポートする関数を作る

それだけ
意外と簡単なんだ
それに、一度作っちゃえば基本的には使い回せるところ多いし、関数や
クラスの頭に DLLTESTHARD_API とか付けるだけだから
そう考えるとすごく簡単そうに聞こえるから不思議ね……
実際、難しいのは動的に関数を使う所だけ
そっか、装飾名とかエクスポートの方法が複雑だったのって、結局それだ
けだもんね
シンプルに使う分には、 DLL はそんなに難しくないってこと
確かに
というわけで、使用例は次回に

/*
    Preview Next Story!
*/
なんども作って、全体像が見えてくるとなんとかなるかも
そう、そういう【手で触った感触】が大事
またわけ分かんないことを
そ、そう?……
というわけで次回
< Version 15.18 一から作った DLL を使ってみる >
につづく!
それに言い方がヤラシイ
ええっ!?
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。