MFCのクラスの派生クラスをスタティックライブラリで作成する方法

[戻る]
オリバ 2007/03/23(金) 10:08:07
VC6SP6 Windows XP

最近、スタティックライブラリの使い方を覚えたのですが、
わからないことがあるので教えて頂きたいです。
お願いします。

現在、ダイアログベースのアプリで、以下の自作クラスを使用しています。
CUtitity  (基本クラス:なし)
CEditEx   (基本クラス:CEdit)
CListBoxEx(基本クラス:CListBox)
CStaticEx (基本クラス:CStatic)

上記4つをスタティックライブラリで作成したいのです。
CUtitityはスタティックライブラリで作成し、関数の実体と宣言をコピーして
メインアプリでライブラリをリンクし、ヘッダをインクルードすることで
今までどうり使用することができました。

しかし、その他3つのクラスは基本クラスから派生させて作成したクラスです。
スタティックライブラリのプロジェクトで、
挿入 ⇒ クラスの新規作成 ⇒ 派生元をCEditにして作成すると以下のダイアログが
表示されます。


「新しいクラスウィザードは基本クラスCEditに対してインクルードするための適切なヘッダーファイルを見つ
けることができませんでした。クラスから派生するために選択した場合、手動で適切なヘッダ
ーファイルを\***\EditEx.hへ追加する必要があります。」

これはCEditが宣言してあるヘッダーファイルをCEditEx.hでインクルードしろ!ということだ
と思うのですが、そのヘッダーファイルの名前がわかりません。
C:\Program Files\Microsoft Visual Studio\VC98\Include
の中でそれらしきヘッダーファイルを探したのですがよくわかりません。

知っている方いましたら教えて頂きたいです。
宜しくお願いします。

Blue 2007/03/23(金) 10:16:55
CEditEx   

という派生クラスを作るときにおそらく

EditEx.h
EditEx.cpp

という二つのファイルが作成されます。
ですので、
>C:\Program Files\Microsoft Visual Studio\VC98\Include
>の中でそれらしきヘッダーファイルを探したのですがよくわかりません。
にはなく、デフォルトであればワークスペースがあるディレクトリに

EditEx.h

があるはずです。

つばさ 2007/03/23(金) 10:17:49
こんちわ

MFCライブラリ リファレンスによりますと
CEditの必要条件 ヘッダー:afxwin.h

とあります

これインクルードすればCEditクラス自体は認識されると思います

Blue 2007/03/23(金) 10:27:55
あ、すみません勘違いしていました。orz

私の発言は無視してください。

オリバ 2007/03/23(金) 12:59:58
afxwin.h
をインクルードしただけでできました。
ありがとうございます。

クラスをスタティックライブラリに変更して、正常動作を確認できたので、
その他のクラスもスタティックライブラリにしようと考えています。

例えば、
CommandLib.libの中に
CAiCmd、CAtCmd、CArCmdとあるとします。

TransactionLib.libの中に
CArcTxRx、Cxxx、・・・とあるとします。

TransactionLibのプロジェクトでCArcTxRxを作成するときに、
CArcTxRxでは、CommandLib.lib内のCAiCmd、CAtCmd、CArCmdの3つのクラスを使用しま
す。
この時にCAiCmd、CAtCmd、CArCmdを使用するためにはヘッダーファイルをインクルードする必
要があると思うのですが。
この場合、TransactionLibのプロジェクトにCommandLibのプロジェクトから各クラスのヘッダーファイル
を持ってくる必要があるのでしょうか?

どのようにしてリンクさせるのか教えて頂きたいです。

つばさ 2007/03/23(金) 13:30:46
CArcTxRxでCAiCmd、CAtCmd、CArCmdを使用したいなら当然ヘッダは必要だと思います。

ですが、TransactionLibフォルダに 上記の3クラスのヘッダファイルを持ってきてしまうと

3クラスの内容を変更したときなど、バージョンの管理がとても面倒になると思います

一般的な方法としましては、普通にTransactionLibのプロジェクトから

CommandLibのフォルダを参照します

そうすることによって CommandLibの内容を変更してもきちんと最新を使用する

ことができると思います。

参照方法は・・#includeのところで パス(絶対パスor相対パス)で見に行かせるか

プロパティ?か何かのとこで参照するパスを設定できるのでそこで設定してください

PATIO 2007/03/23(金) 14:33:11
> プロパティ?か何かのとこで参照するパスを設定できるのでそこで設定してください

VC++6.0なのでプロジェクトの設定のC++/Cのタブを選択して
カテゴリをプリプロセッサにすると追加のインクルードパスと言うのが
あると思いますのでここにライブラリのヘッダーファイルがあるパスを入れておけば、
#Include文でパスを指定しなくてもヘッダーファイルの参照が可能になります。

ツールのオプションでディレクトリのタブに設定する事も出来ますが、
ここはプロジェクトに共通して使用するパスを設定するべき場所なので
プロジェクト特有の設定はここに入れないほうが良いと思います。

ライブラリも同一ワークスペースに入れておくと設定をある程度簡略化できます。
他のプロジェクトにも流用したいような場合は別ワークスペースにしておいた方が
管理しやすいかもしれません。

オリバ 2007/03/27(火) 15:47:30
>VC++6.0なのでプロジェクトの設定のC++/Cのタブを選択して
>カテゴリをプリプロセッサにすると追加のインクルードパスと言うのが
>あると思いますのでここにライブラリのヘッダーファイルがあるパスを入れておけば、
>#Include文でパスを指定しなくてもヘッダーファイルの参照が可能になります。

CommandLibプロジェクト内のクラス「CBs」で
下記ヘッダーをインクルードしているので、以下のようにパスを入れましたが、
「../CommPortLib/CommPort.h ../ExtensionLib/ListBoxEx.h」


error C2061: 構文エラー : 識別子 'CListBoxEx' がシンタックスエラーを起こしました。
などのエラーがでてしまいます。

ITO 2007/03/27(火) 19:07:23
スタティックライブラリーを使う側でも、
スタティックライブラリーを作る時に使った
 「STDAFX.H STDAFX.CPP」を使えばうまくいくと思いますが......


スタティックライブラリーを使う利点は、
  「MFCXX.DLL」なくても実行できる。
だと思いますが..........

オリバ 2007/03/27(火) 23:43:38
>スタティックライブラリーを使う側でも、
>スタティックライブラリーを作る時に使った
> 「STDAFX.H STDAFX.CPP」を使えばうまくいくと思いますが......
すいません、言ってる意味が理解できないのですが・・・

CommandLibとCommPortLibとExtensionLibは三つともスタティックライブラリです。
それぞれのプロジェクトに「STDAFX.H STDAFX.CPP」はありますが・・・
> 「STDAFX.H STDAFX.CPP」を使えばうまくいくと思いますが......
使うとはどういう意味ですか?

オリバ 2007/03/27(火) 23:59:09
もう少し詳しく説明します。
スタティックライブラリで新規プロジェクト「CommandLib」を作成しました。
これに「CBs」というジェネリッククラスを作成しました。
bs.cppでは"stdafx.h"と"bs.h"しかインクルードしていません。

"bs.h"でCListBoxEx* m_pLB;というメンバ変数を宣言しています。
今、この型がわからないというエラーが出ています。

CListBoxExという型は、別のスタティックライブラリプロジェクト「ExtensionLib」で
作成したクラス「CListBoxEx(CCListBoxが基本クラス)」のクラスです。

「CommandLib」プロジェクト内のクラス内で「ExtensionLib」のクラスを使いたいというこ
とです。

つばさ 2007/03/23(金) 13:30:46
PATIO 2007/03/23(金) 14:33:11
で示された通りやってみたのですが、どれもできません。

やりかたが意図したものと違うのかもしれません。
もうちょっと具体的に教えていただけないでしょうか?
例をあげて説明してもらえると助かります。

つばさ 2007/03/28(水) 09:25:15
えーっと

自作されたCListBoxEx というクラスも
元々ある CListBoxやC〜とかいうMFCクラスも
特に使用方法に違いはありませんので

普段MFCのクラスを使用してるのと同じようにCListBoxExが定義されている
ヘッダ、ライブラリをきちんと読み込むようにだけすれば
問題なく使用できるはずですが;

PATIO 2007/03/28(水) 12:43:55
スタティックリンクライブラリの場合、ライブラリを使用するアプリケーションの方に
関連するライブラリが全てリンクされていれば良いはずです。
各スタティックリンクライブラリは特にリンクの必要が無かったと思います。
そこがクリアできていれば、この記述は釈迦に説法ですが。

ヘッダーファイルに関してはそのクラスなり関数を使用する為の宣言がほしいだけなので
原則的には使うそのクラスを使用するヘッダーファイルやソースファイルに
インクルードしていればいいだけの話です。
この場合、追加のインクルードパスを設定するのはライブラリを使用する側のプロジェク
トになります。
ライブラリ側のプロジェクトに設定しても意味がありませんよ。
使用する側のプロジェクトと同一フォルダ内にヘッダーファイルが存在しないから
ヘッダーファイルが存在するパスを予めプロジェクトに指定しておく事で
コンパイラがファイルを探す事ができるようにするのがプロジェクトの追加の
インクルードパスの目的です。
この辺は、それぞれ何の為にしなくてはいけないのかと良く考えてみてください。
目的がわかれば、自ずと何処に設定する必要があるのかわかるはずです。

2007/03/28(水) 14:37:28
>bs.cppでは"stdafx.h"と"bs.h"しかインクルードしていません。
>"bs.h"でCListBoxEx* m_pLB;というメンバ変数を宣言しています。
>今、この型がわからないというエラーが出ています。
全ての型はそれを宣言しているヘッダを読み込んでから使いましょうね。

>スタティックリンクライブラリの場合、ライブラリを使用するアプリケーションの方に
>関連するライブラリが全てリンクされていれば良いはずです。
補足させてもらいます。
スタティックライブラリは、アプリケーションをリンクする段階で必要なものが全てリン
カに指定されていればいいです。
指定方法には、オブジェクトファイルにリンク指定を埋め込む場合と、リンカに直
接リンク指定を渡す方法があります。
プロジェクト設定からはリンカに渡す設定が編集でき、ソースコードのPragmaで
指定するとオブジェクトファイル中に指定を埋め込めます。

MFC以外の場合も、参照するヘッダをインクルードして、そのファイルをリンクする
際に参照したライブラリを指定します。

MFCクラスから派生するクラスや、MFCの機能を利用する場合は、MFCのヘッダ
をインクルードするファイルにPragmaを埋め込んだほうが指定ミスは少ないと思い
ます。
プロジェクトで設定する場合は、リンクするオブジェクトファイルが必要としているラ
イブラリを全て探して手作業で埋め込み、使用するライブラリが変わるたびに影
響する全ての設定をこれまた手作業で直す作業が必要です。

オリバ 2007/04/02(月) 09:44:02
返事遅くなりました。
出張などでバタバタしていたもので・・・


>オリバ 2007/03/27(火) 23:59:09
上の記述で、
"bs.h"内で
#include "../ExtensionLib/ListBoxEx.h"
をインクルードすれば「CommandLib」でリビルドすればエラーはなくなりました。

しかし、この「CommandLib.lib」を使う側のプロジェクト「MainPjct」では、
「Debug」「Release」フォルダ内に「CommandLib.lib」をコピーします。
そして、「MainPjct」の直下に「command」、「extension」という名前でフォルダを作
成し、それぞれのフォルダの直下に各ライブラリのヘッダーファイルをおいています。
そうすると、"../ExtensionLib/ListBoxEx.h"などのパスが変わるのでリビルドするとエ
ラーになります。

この場合、"bs.h"内のインクルード文のパスを変更してもよいのでしょうか?
また、ダメなのであればどうするべきですか?


>指定方法には、オブジェクトファイルにリンク指定を埋め込む場合と、リンカに直
>接リンク指定を渡す方法があります。
これは知らなかったです。
>オブジェクトファイルにリンク指定を埋め込む場合
この使い方がいまいちわかってなかったです。
両方やっても、「リンカに直接リンク指定を渡す方法」だけでも同じだったので
プラグマ指定は意味あるの?っと思っていました。

そこで質問があります。
「CommPortLib」というスタティックライブラリのプロジェクトがあります。
出力されるライブラリは「CommPort.lib」です。
そのプロジェクトの"CommPort.h"の先頭で、

#pragma comment(lib,"CommPort.lib")

と記述しました。
「CommPort.lib」を使う側のプロジェクト「MainPjct」の「Debug」「Release」フォルダ内
に「CommPort.lib」をコピーします。
そして、リビルドすると、
リリースのほうは通るのですがデバッグのほうで
LINK : fatal error LNK1104: ファイル "CommPort.lib" を開けません。
というエラーがでます。

パスがあっていないからだと思い、
"CommPort.h"で、以下のように記述を変更したら問題なくリビルドとおりました。

#ifdef _DEBUG
#pragma comment(lib,"Debug/CommPort.lib")
#else
#pragma comment(lib,"Release/CommPort.lib")
#endif

しかし、これはライブラリを使う側の「MainPjct」の直下にヘッダーがあり、
「Debug」「Release」フォルダ内に「CommPort.lib」があるとき限定だと思います。
どうすればいいのでしょうか?

PATIO 2007/04/03(火) 11:50:49
結局、プロジェクト構成をどうするのかと言う話になると思うのですが、
特定のアプリケーションにしか使いませんと言うライブラリであれば、
使う側のプロジェクトフォルダに必要なファイルを全てコピーすると言う手も
使えなくないですが、この方法だと使用する側のプロジェクト複数にわたる場合に
ライブラリ側の変更を反映する為に使用するプロジェクト毎に
ファイルをコピーする必要が出てくるので面倒です。

ビルド場所の変更とかライブラリ側の修正を即時反映したいとか考える場合は、
きちんとワークスペース単位でどういう構成にするかを考える必要があります。
例えば、

WorkSpace +
          |
          +- Static Link Library A Project +
          |                                |
          |                                +- Debug
          |                                |
          |                                +- Release
          |
          +- Application Project +
                                 |
                                 +- Debug
                                 |
                                 +- Release

こういう風に構成する事を予め決めておいてアプリケーション側は、
追加のインクルードパスを相対アドレス指定でStatic Link LibraryA Projectに
設定します。
更にアプリケーションのDebug時のライブラリパスを相対アドレス指定で
Static Link LibraryA ProjectのDebugに、Release時のライブラリパスを
相対アドレス指定でStatic Link Library A ProjectのReleaseにすれば、
WorkSpaceを何処に持っていってもビルドできる環境が構築できます。

逆にライブラリ側の開発も他の人が並行で行っていて
途中のバージョンは動かない可能性があるような場合は、あえてコピーする方法を
取る場合もありますが、それでもアプリケーション側のプロジェクトフォルダに
コピーするような事は普通しません。


WorkSpace +
          |
          +- Include
          |
          +- Lib +
          |      |
          |      +- Debug
          |      |
          |      +- Release
          |
          +- Application Project +
                                 |
                                 +- Debug
                                 |
                                 +- Release

このようにリリース版のライブラリとライブラリのインクルードファイルを
置く場所を決めておいて動作確認が取れたものだけを各フォルダにリリース(コピー)
するようにします。
こうした上でライブラリを使用する側(この場合はApplication Project)は、
相対パスで追加インクルードパスとライブラリパスの設定をしておくわけです。
このパス設定をきちんとしておけば、インクルードやライブラリの指定時に
パスを記入する必要はなくなります。コンパイラやリンカがファイルを探して
くれるからです。

ワークスペースとプロジェクトの関係とかプロジェクトファイル上で
プロジェクト外のインクルードファイルやライブラリファイルがどういう扱いに
なっているのかをきちんと把握した上で考えないとうまく行きませんので
実験用にプロジェクトを起こして色々実験してみる事をお勧めします。

PATIO 2007/04/03(火) 11:52:11
ちなみに上記のような構成をしたい場合は空のワークスペースを
予め作成しておいてそれにプロジェクトを追加するようにすると
出来ますのでやってみると良いと思います。

オリバ 2007/04/03(火) 14:29:48
[[解決]]
WorkSpace +
          |
          +- Include
          |
          +- Lib +
          |      |
          |      +- Debug
          |      |
          |      +- Release
          |
          +- Application Project +
                                 |
                                 +- Debug
                                 |
                                 +- Release


この方法は確かにいいですね!!
>相対パスで追加インクルードパスとライブラリパスの設定をしておくわけです。
この方法も色々試しているうちに理解できるようになりました。

>ちなみに上記のような構成をしたい場合は空のワークスペースを
>予め作成しておいてそれにプロジェクトを追加するようにすると
>出来ますのでやってみると良いと思います。
やってみました。
この方法の場合、ライブラリのヘッダファイルをアプリケーションプロジェクトに追加しなくて
もインクルードするだけで使用できるのですね。


色々、勉強になりました。
ありがとうございます。

古いスレッドには追加発言できません。