共有ライブラリの中でスレッドクラスを定義。アプリからそのスレッド利用したい。 – プログラミング – Home

共有ライブラリの中でスレッドクラスを定...
 
通知
すべてクリア

[解決済] 共有ライブラリの中でスレッドクラスを定義。アプリからそのスレッド利用したい。


KJ
 KJ
(@KJ)
ゲスト
結合: 21年前
投稿: 52
Topic starter  

以下の質問について、どうかご教授願えますでしょうか。

【やりたい事】
あるアプリケーションでスレッドを利用する。スレッドクラスは、共有ライブラリの中で
定義している。

【結果】
リンク時に下記のエラーが発生します。
AAADlg.obj : error LNK2001: 外部シンボル "public: static struct CRuntimeClass
const Thread::classThread (?classThread@Thread@@2UCRuntimeClass@@B) は未解決です
Debug/AAA.exe : fatal error LNK1120: 外部参照 1 が未解決です。
link.exe の実行エラー

【開発環境】
・WindowsXP
・Visual C++ 6.0(サービスパック6)

当方で行った事は以下の通りです。

「MFCプロジェクト作成」
1. AAAという名前のプロジェクト作成する。
MFC AppWizard(exe)を選択。ウィザードは全てデフォルト。

2. DLLのThreadクラスヘッダをインクルードする。
BBB/Thread.hを記述する。

3. DLLをリンクする。
プロジェクトの設定→リンク→オブジェクト/ライブラリモジュールに、「BBB/Debug
/BBB.lib」を記述する。

4. ボタンを追加し、クリック時にスレッドが作成されるようにする。
OnButton1()に以下のコードを追加。
CRuntimeClass *pRuntime = RUNTIME_CLASS(Thread);
Thread *pThread = (Thread*)pRuntime->CreateObject();
pThread->CreateThread(0, 0, NULL);

「DLLプロジェクト作成」
1. BBBという名前のプロジェクト作成する。
MFC AppWizard(dll)を選択。MFCのスタティックライブラリを使用した標準DLLに
チェック。

2. Threadという名前のスレッドクラスを追加する。
クラスの種類は「MFCクラス」、基本クラスは「CWinThread」を継承する。

なお、AAAとBBBのフォルダ構成は以下の通り。
AAA - BBB - Debug
・Thread.h ・BBB.dll
・BBB.lib


引用未解決
トピックタグ
wclrp ( 'o')
 wclrp ( 'o')
(@wclrp ( 'o'))
ゲスト
結合: 18年前
投稿: 287
 

直接の答えではない。
MFCのクラスなどを渡す場合
バージョンとかリリース/デバッグビルドとかコンパイルの設定とかの違いで
互換性なくなる。
EXEとDLLでともにバージョンとかリリース/デバッグビルドとかコンパイルの設定を
同一に保たなければいけない。
またEXEとDLLでともにMFCはDLL版を使うなどの制限が付くよ。

BBB.dllでThreadクラスはdllexportしてる?
AAAでThreadクラスをdllimportしてる?


返信引用
KJ
 KJ
(@KJ)
ゲスト
結合: 21年前
投稿: 52
 

wclrp ( 'o')さん、ご回答ありがとうございます。

>BBB.dllでThreadクラスはdllexportしてる?
>AAAでThreadクラスをdllimportしてる?

両方ともしてません。
ただ、これをしなくても実行時に問題が出るだけで、リンクは通ってもいいんじゃない?
と思ってます。。

なお、更に調べたところ、
CRuntimeClass *pRuntime = RUNTIME_CLASS(Thread);
の行でリンクエラーが発生してます。

プロジェクトを分けた場合に、以下のような制約はあるのでしょうか?
片方のプロジェクトで、
・「DECLARE_DYNCREATE」と「IMPLEMENT_DYNCREATE」を使用したクラスを定義
もう片方のプロジェクトから、
・「RUNTIME_CLASS」を使ってCRuntimeClassを得る


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

exportしていないクラスや関数はDLL外部からは見えないと
思いましたけれど。
多分、インポート用のライブラリに情報が出てこないと思います。
exportされていないクラスは外部公開されていないクラスなので
基本的にはリンクできないと思うのですけれど、
リンクは出来て良いという話は何処から来ているのでしょう?

プロジェクトを分けない場合、プロジェクト内部でのリンクは
objファイルのリンクで行なわれますからexportする必要は有りませんが、
プロジェクトを分けてしまうと別のロードモジュールになってしまうので
exportでモジュールの外部に公開しないと外部からは参照できないと思います。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

後学の為に聞いておきたいのですが、

「RUNTIME_CLASS」を使ってCRuntimeClassを得てからCreateObjectしている意味は
何でしょう?
こうすればインスタンスを作成できるのはわかりますが、
そうする理由が良く分からないので。
普通にnewで作成するのと何が違うのかなと。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

うーーん、
UIスレッドを作りたいのかな?
MFCの場合、拡張DLLになるのでスタティックリンクは出来ないですね。

> 「DLLプロジェクト作成」
> 1. BBBという名前のプロジェクト作成する。
> MFC AppWizard(dll)を選択。MFCのスタティックライブラリを使用した標準DLLに
> チェック。
共有DLLを使用した拡張DLLですね。

なので、wclrpさんの意見どおり、互換性の問題が発生します。

> 2. Threadという名前のスレッドクラスを追加する。
> クラスの種類は「MFCクラス」、基本クラスは「CWinThread」を継承する。
追加→クラスの新規作成で追加したのなら、

> CRuntimeClass *pRuntime = RUNTIME_CLASS(Thread);
> Thread *pThread = (Thread*)pRuntime->CreateObject();
これはいらないですね。


返信引用
KJ
 KJ
(@KJ)
ゲスト
結合: 21年前
投稿: 52
 

皆様、ご教授ありがとうございます。一応、下記方法で解決しました。
ただ、これでは不十分だ!と言う点がございましたら、ご指摘頂けると助かります。

DLLプロジェクトで「共有DLLを使用した拡張DLL」にチェックし、公開するThreadクラス
に「AFX_EXT_CLASS」キーワードをつけたら、別プロジェクトから生成し、使用すること
が出来ました。

以下、皆様の質問にお答えして参ります。

PATIOさん
>リンクは出来て良いという話は何処から来ているのでしょう?
「プロジェクトの設定でBBB.libをリンクしているから、シンボルは解決できるんじゃな
いの?」と考えての発言でした。(調べたわけではありません。実際、MFC派生クラス以外
は解決できてましたので・・・)
dllexportやexportもしくは、.defファイルで定義するなど必要だったんですね。。

>普通にnewで作成するのと何が違うのかなと。
ITOさんのおっしゃる通り、UIスレッドを作成する為です。

ITOさん
>これはいらないですね。
申し訳ありません。いらないというのがよくわかりませんでした。
別の宣言の方法を使え、ということでしょうか?


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

> これはいらないですね。
>> 申し訳ありません。いらないというのがよくわかりませんでした。
>> 別の宣言の方法を使え、ということでしょうか?

>> クラスの種類は「MFCクラス」、基本クラスは「CWinThread」を継承する。
> 追加→クラスの新規作成で追加したのなら、
これを、行なえば「Thread」クラスのソースリストに
> CRuntimeClass *pRuntime = RUNTIME_CLASS(Thread);
> Thread *pThread = (Thread*)pRuntime->CreateObject();
が組み込まれます。
あとは、UIスレッドとして動作させれば動くはずです。 
ただ、DLLで「UIスレッド」を動作させるのはあまりお勧めできません。
どうしても必要ですか?


返信引用
KJ
 KJ
(@KJ)
ゲスト
結合: 21年前
投稿: 52
 

ITOさん

ありがとうございます。理由がわかりました。

>ただ、DLLで「UIスレッド」を動作させるのはあまりお勧めできません。
UIスレッドを選んだ理由としては以下の通りです。

これは以下の理由からです。
まず、このスレッド(以下スレッドA)は更に別のスレッド(以下スレッドB)と通信を行う必
要があります。

その通信方法としては、以下の通りです。
1. スレッドAから他社提供DLLの公開APIをコールする
2. 公開APIの中でスレッドBが生成され、公開APIはリターンする
3. スレッドBからスレッドAへのメッセージを待つ

ここで、スレッドBが実装しているメッセージ送信関数は「PostMessage」のようなので
す。(提供されたDLLの為、実装は確認できないのですが、公開APIの引数がHWNDとなって
いるので恐らくそうかと)

よって、スレッドAはウインドウを持つ必要がある為、UIスレッドを選択しました。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

>ここで、スレッドBが実装しているメッセージ送信関数は「PostMessage」のようなの
>です。(提供されたDLLの為、実装は確認できないのですが、公開APIの引数がHWNDとな
>っているので恐らくそうかと)
公開している人に聞いてみるのもいいと思います。

UIスレッドを薦めない理由ですが、
1.UIに限らずにスレッドをDLLに組込むこと自体が難しい。
   ・引継ぐ変数をどうするか?
   ・終了の方法等
 2.UIスレッドに限った問題
   ・親スレッドがAPIのためHWNDの継承が難しい。
    「HWND == NULL」になり、例外で異常終了になりやすい。
    HWNDのチェックが必要。
 3.メッセージ処理の問題

でしょうか。

探すとまだありそうに思えます。


返信引用
KJ
 KJ
(@KJ)
ゲスト
結合: 21年前
投稿: 52
 

問題は解決したので閉じます。

皆様、ありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました