スタティックライブラリとDLLの活用方法


新宿二丁目  2004-01-16 01:03:08  No: 53059

VC++6.0 WindowsXP HomeEditionの環境を使用しています。
VCを初めて3ヶ月足らずになり、いろんな悩みが出てきてしまいました。
どうも、静的ライブラリとDLLの使い分けで一線を引けないく
悩んでいます。

以下に、Win32 Static Libraryを作成しました。
--- ASample.H ---
  class ASample{
      public:
          ASample(){}
          void smpFunction();
          void smpFunction(int in);
  };

--- ASample.CPP ---
#include <windows.h>
#include <ASample.h>

ASample::smpFunction(){
    ::MessageBox(NULL, "Message-smpFunction()", "", MB_OK);
}
ASample::smpFunction(int in){
    ::MessageBox(NULL, "Message-smpFunction(int)", "", MB_OK);
}

以下に、ダイアログベース(XXX)のEXEを作成しました。
--- CXXXDlg.CPP ---
#include <ASample.h>
<中略>

void ボタン_クリックイベント(){
    ASample    *s = new ASample;
    s->smpFunction();
    delete s;
}

この時に、EXE側に以下のオプション設定、プロジェクト設定をしています。
・インクルード先、ライブラリ参照先の追加
・プロジェクト設定で明示的に静的ライブラリを設定

これで、エラーもなく正常に実行されます。
静的DLLと比べると、比較的つくり込みが楽なのはライブラリ化だと思って
いるのですが、単純にDLLはサイズが軽いっていうだけの特性では
ないですよね?

すいません、いろいろアドバイスお願いします。


YuO  2004-01-16 03:02:36  No: 53060

> どうも、静的ライブラリとDLLの使い分けで一線を引けないく
> 悩んでいます。

悩んだらとりあえず静的ライブラリにしておいて問題ないと思います。
CRTの問題がある程度で,それほど問題は起きないと思います。
see) http://madia.world.coocan.jp/cgi-bin/Vcbbs/wwwlng.cgi?print+200307/03070025.txt

CRTの問題が面倒であれば,DLLにした方が楽かもしれませんけど……。
#デバッグはDLLの方が面倒かもしれない。

> これで、エラーもなく正常に実行されます。
> 静的DLLと比べると、比較的つくり込みが楽なのはライブラリ化だと思って
> いるのですが、単純にDLLはサイズが軽いっていうだけの特性では
> ないですよね?

DLLにするのは,基本的に
・プラグインとして利用する場合
・OSによって切り分ける場合
#OSによって,DLLそのものを入れ替えてしまう。
・関数名を名前で指定したい場合
・VBなど,別の処理系から呼び出す場合
と思えばよいです。


新宿二丁目  2004-01-16 03:54:59  No: 53061

YuOさん、レスありがとうございます。

>悩んだらとりあえず静的ライブラリにしておいて問題ないと思います。
>CRTの問題がある程度で,それほど問題は起きないと思います。
CRTの問題・・・全然意識もしていなかったですが、CRTのどういった問題なんですか?
ご指摘頂いた過去ログを見てみましたが、今の自分にはちょっと理解不能に近い
領域でした(T_T;

>DLLにするのは,基本的に
>・プラグインとして利用する場合
すいません、"プラグイン"という意味がわかりませんでした (T_T;
用語辞典等で調べてみます。

>・OSによって切り分ける場合
>#OSによって,DLLそのものを入れ替えてしまう。
"DLLはマルチプラットホームに対応している"と理解してよいのでしょうか。
(作成したDLLがAPIを使用した(MFC未使用)場合と捕らえてよいでしょうか)

>・関数名を名前で指定したい場合
名前で指定というのは、動的なDLLの場合に適用されるアレ(GetProcAddress??でしたっけ)ですか?

>・VBなど,別の処理系から呼び出す場合
>と思えばよいです。
なるほど。開発言語がVCだけであればLIBでも問題ないが
他の開発環境でも共通に使用する場合は、DLL形式でないと連携できないと
いう理解でよいでしょうか。

質問ばかりで申し訳ありません。
※関係ないですが、なんでHNが"新宿二丁目"になってるんだ!?


YuO  2004-01-16 07:05:36  No: 53062

> CRTの問題・・・全然意識もしていなかったですが、CRTのどういった問題なんですか?
> ご指摘頂いた過去ログを見てみましたが、今の自分にはちょっと理解不能に近い
> 領域でした(T_T;

CRTには,
・シングルスレッド/リリース用(CRT本体はLIBとして提供)
・シングルスレッド/デバッグ用(CRT本体はLIBとして提供)
・マルチスレッド/リリース用(CRT本体はLIBとして提供)
・マルチスレッド/デバッグ用(CRT本体はLIBとして提供)
・マルチスレッド/リリース用(CRT本体はDLLとして提供)
・マルチスレッド/デバッグ用(CRT本体はDLLとして提供)
の6種類があります。

利用するCRTは,モジュールに含まれる全てのオブジェクトファイルで全て一致させなければいけません。
そうでないと,LNK4098の警告が起きます。
全てのオブジェクトファイルには,ライブラリに含まれるオブジェクトファイルを含みますが,
DLLを構成するオブジェクトファイルは含みません。

警告だけならよいのですが,場合によっては実行時にAccess Violationを引き起こしたりします。
#主に問題を起こすのはリリースとデバッグ。

DLLはEXEとは別にCRTがリンクされているので,DLLでmallocしたメモリをEXEでfreeしたり,
その逆は基本的に出来ません。
#LIBでは問題なく行える。
それをするためのものが,最後の二つのDLLとして提供されているCRTです。
EXEとDLLで共通のCRT-DLLを利用している場合,DLLでmallocしたメモリをEXEでfreeしたりすることが可能になります。

> >・OSによって切り分ける場合
> >#OSによって,DLLそのものを入れ替えてしまう。
> "DLLはマルチプラットホームに対応している"と理解してよいのでしょうか。

そうではないです。

同じことをしたくても,NT系と95系で手段が異なる場合があります。
#例えば,プロセスの列挙。
その場合に,
a) プログラム中に分岐を設ける
  OSの情報を取得して,それを元にifで分岐することで手段を変化させます。
b) EXEをごっそり入れ替える
  NT系用のEXEと95系用のEXEを別に用意しておいて,インストール時にどちらかをインストールします。
c) DLLをごっそり入れ替える
  インストール時にOSにあったDLLをインストールすることで,分岐を無くします。
の三通りの方法が考えられます。

bの方法は実行における効率が一番よいのですが,
非常に面倒であることはすぐにわかると思います。

で,aの方法が一般に行われますが,局所的にあるならともかく,
片っ端からif文が出てくるとデバッグが大変になります。

そこで,cの方法を採ることがあります。
cの方法は,aのif文をインストール時に決定してしまう方法です。

インストール時に,
・NT系OSにインストールした場合はfoo_nt.dllをfoo.dllに改称してインストール
・95系OSにインストールした場合はfoo_95.dllをfoo.dllに改称してインストール
ということを行うことで,cを簡単に実現できます。

OSによる場合分けではないですが,EXE自体はI18N(InternationalizatioN:国際化)を行っておき,
言語や地域に依存する処理はDLLに行わせる(L10N/LocalizatioN:地域化)を行う,
ということもできます。
#Windows NT系列のOSではこれが行われている……はず……。

例えば,
・EXE本体:各国共通
・foo_en-GB.dll : 英語/イギリス用
・foo_en-US.dll : 英語/アメリカ用
・foo_ja-JP.dll : 日本語/日本用
のように,言語や地域によってdllを分割しておくと,
例えばfoo_en系では多バイト文字の対応は基本的にいらないですし,
スペルの若干違うイギリス英語とアメリカ英語(colourとcolor等)にも対応できます。
当然,メニューなどは各国語用に地域化を行うことが出来ます。
#まぁ,文字列やメニューなどはリソースで処理できるのですが。

> >・関数名を名前で指定したい場合
> 名前で指定というのは、動的なDLLの場合に適用されるアレ(GetProcAddress??でしたっけ)ですか?

そうです。


新宿二丁目  2004-01-16 20:24:25  No: 53063

YuOさん、詳細なアドバイスありがとうございます。

今まで YuOさんからアドバイスを受けていた中での "CRT" という言葉を
単純に"画面"のこと(?)と思って考えてしまっていましたが、
実は、
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vclib/html/_crt_c_run.2d.time_libraries.asp
に記載していることのことだったのでしょうか。
(すいません、今気付いてしまって)

CRT = MSVCRT.LIB(DLL)


YuO  2004-01-16 22:49:26  No: 53064

http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vclib/html/_crt_c_run.2d.time_libraries.asp
> に記載していることのことだったのでしょうか。

そうです。

> CRT = MSVCRT.LIB(DLL)

LIBC.LIB, LIBCD.LIB, LIBCMT.LIB, LIBCMTD.LIB, MSVCR71.DLL/MSVCRT.DLL(with MSVCRT.LIB), MSVCR71D.DLL/MSVCRTD.DLL(with MSVCRTD.LIB)
の6つが実際のライブラリです。

MSVCRT.LIBはマルチスレッド/リリース用で本体がDLLに含まれるタイプのDLLを静的にリンクするための,
インポートライブラリに過ぎません。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加