いつもお世話になります。
EXE(VC6)とDLL(VC6)の構成にて、VC6ではDLLにてAfxGetApp()を行っても
正常な値が返ります。
EXE(VC9)とDLL(VC6)の構成では、NULLが返ってきます。
これは、コンパイラの問題でしょうか?
VC6同士ではたまたま動いたということでしょうか?
DLL(VC6)にてAfxGetApp()など使わないように変更することは、不可能な
話ではないのですが、DLLを変更せず、上位EXE(VC9)側の変更にて対応
することは可能でしょうか?
わかる方いらっしゃいましたら、ご教授願います。
質問がよくわかりません。
AfxGetApp()はアプリケーションにただ 1つしかないCWinAppオブジェクトへのポイ
ンタを返しますが、MFCで作成した場合、CWinAppオブジェクトはExeとDLLの両方に
存在して、其々でそのポインタを返します。つまり、ExeのAfxGetApp()とDLLの
AfxGetApp()は別のものを指すわけです。
> EXE(VC9)とDLL(VC6)の構成では、NULLが返ってきます。
とはどういう状況をいっておられるのでしょうか?
EXE(VC9)側でNULLが返ってくるのであれば、DLLとは無関係の問題と思われます。
自分は実際には遭遇したことはありませんが、
関係ありそうな情報は以下のものです。
MFCで呼び出し側の状態(モジュール状態)を使用するには、
AFX_MANAGE_STATEマクロを使う必要があります。
・MFC と動的にリンクされるレギュラー DLL のモジュール状態
・MFC モジュールの状態データの管理
・テクニカルノート58:
・ http://support.microsoft.com/kb/140850/ja
等を参考にして、DLL側を変更する必要があるかもしれません。
ただ、これらの方法は「DLL側」の変更になるため、
>DLL(VC6)にてAfxGetApp()など使わないように変更することは、不可能な
>話ではないのですが、(引用者が省略)
であれば、そのように変更したほうが良い場合もありえます。
おっと、かぶったので、やや補足(^^;)。
MFC4.x(だったかな)のころは、DLL側でAfxGetAPP()しても呼び出し側
のCWinAppが取得できていたのです。
その頃のソースではないかと推測できます。
> MFC4.x(だったかな)のころは、DLL側でAfxGetAPP()しても呼び出し側
> のCWinAppが取得できていたのです。
なるほど、そんな時代があったんですね。
http://msdn.microsoft.com/ja-jp/library/3z02ch3k(v=VS.90).aspx
によれば、MFC4.0はVC++4.0の頃。たしか、その頃はWIN32 APIでコードを書いて
いたような気がする。だから、そんな知識がありませんでした。
もしそうだとすると、DLL側も直す必要がありますね。
でも、これ
> EXE(VC6)とDLL(VC6)の構成にて、VC6ではDLLにてAfxGetApp()を行っても
> 正常な値が返ります。
はDLL側でAfxGetApp()をやって、EXE側のCWinAppを取得できたってことですよね。
ほんとにそんなことできるんだろうか?
ってことで実験をしてみました。
VC6のDLLでDLL側のCWinAppのインスタンスが存在しない状態でAfxGetApp()を呼び出し
て見ましたが、0が返ってきて、Exe側のCWinAppなんて取得できませんでした。
> 正常な値が返ります。
とは、どういうことでしょうかね?
>ってことで実験をしてみました。
>VC6のDLLでDLL側のCWinAppのインスタンスが存在しない状態でAfxGetApp()を呼び出し
>て見ましたが、0が返ってきて、Exe側のCWinAppなんて取得できませんでした。
>> 正常な値が返ります。
>とは、どういうことでしょうかね?
だと、思います(vv;)。
そこはスレ主さんに、何か勘違いがあるのではないかと思いましたが、
maruさんが、既に指摘済みなので・・・OKっと。
皆さん、いろいろとありがとうございます。
私もダイアログベースでテストプログラムも作成して再度確認してみました。
1.VC6でDLLを作成
この中でAfxGetApp()をコールする
2.VC6とVC9でEXEを作成
DLLの関数をコールする(LoadLibraryとGetProcAddress)
結果、
VC6(EXE)とVC6(DLL)では、
(EXE)OnInitDialogでAfxGetApp()-->0x004167a0
(DLL)呼ばれた関数でAfxGetApp()-->0x004167a0
VC9(EXE)とVC6(DLL)では、
(EXE)OnInitDialogでAfxGetApp()-->0x00af7310
(DLL)呼ばれた関数でAfxGetApp()-->0x00000000
となりました。
皆さんの言っていることと矛盾しているようですが、実際できています。
よくわかんなくなってきました。
DLL側がデバッグできると言うことはソースコードは持ってるんですよね?
だとすると、簡単にできそうな話で1つ抜けている気がするのですが、
VC6のDLLをVC9でビルドし直した上で、
EXE(VC9) → DLL(VC9)
はどうでしょうか?
あと、DLLにもいろんな種類があります。
> VC6(EXE)とVC6(DLL)では、
> (EXE)OnInitDialogでAfxGetApp()-->0x004167a0
> (DLL)呼ばれた関数でAfxGetApp()-->0x004167a0
同じアドレスを返すと言うことは、MFCの拡張DLLですか?
拡張DLLの場合、クラスごとエクスポートしますので、
EXEとDLLのMFCは同じ物(バージョン)でないとまずい気がします。
> 皆さんの言っていることと矛盾しているようですが、実際できています。
VC6がないから実験できませんが、取得できたとしてもCWinAppの定義が
VC6とVC9とでは変わってませんか?VC9のCWinAppへのポインタを
VC6のCWinAppへのポインタとみなして処理するんでしょ?
成功したとしても、それこそたまたま動いているとしか評価できないのですが。
> DLL側がデバッグできると言うことはソースコードは持ってるんですよね?
いえいえ、テスト用に作って試しているだけです。
で、EXE(VC9) → DLL(VC9)をテストしてみました。
(EXE)OnInitDialogでAfxGetApp()-->0x008f7310
(DLL)呼ばれた関数でAfxGetApp()-->0x008f7310
と問題ありませんでした。
bun様と言う通り、拡張DLLを使用していますので、そこが問題と
言うことでしょうか?
これから、拡張DLLでないタイプで試してみます。
VC6で作ったexeとdllがあって、どっちもVC9にバージョンアップさせたいけど、
dllのソースコードはない、という状況ですか?
dll側では、exeのCWinApp*を取得して、何に使っているのかわかりますか?
MFCの共有DLLを使用で行ってみました。
(EXE)OnInitDialogでAfxGetApp()-->0x00307310
(DLL)呼ばれた関数でAfxGetApp()-->0x00000000
結果、とれませんでした。
> VC6で作ったexeとdllがあって、どっちもVC9にバージョンアップさせたいけど、
> dllのソースコードはない、という状況ですか?
もともと、EXE(弊社)、DLL(他社)にてVC6で作成していました。
そして、双方ともVC9へバージョンアップを計画していましたが、
DLLができない状態にあり、VC9(EXE)とVC6(DLL)の組み合わせでテストしています。
> dll側では、exeのCWinApp*を取得して、何に使っているのかわかりますか?
AfxGetApp()->GetProfileInt()やCWaitCursorなど、他にもありそうです。
他社にAfxGetApp()を使用している箇所を修正してもらうことは可能だと
思われますが、全ての項目を再チェックしなければならなく、上位(EXE)側の修正
のみで行えないものかと思っています。
dllをVC9に変更することはできないけど、VC6のまま若干の修正なら可能ということですか?
例えば、古いハードの制御のために、dllはVC6で作らざるを得ない、
というような事情があれば、ソースコードがあっても仕方ないですね。
dllを変更してしまうとdll側のテストもやり直しになりますが、
無理してexeだけの変更で対応させることに成功したとしても、
無理した分、それなりのテストが必要ですし、何より怖いのが、
Windows Update等で動かなくなる可能性が付きまとうことです。
VCのバージョンに依存しない形にdllも変更してもらうしかないと思いますが。
コストとリスクを評価してみてください。
# VC9のCWinAppのインスタンスをVC6のCWinAppとして使用することについて、
# 何の保証もない、という私の認識が正しかった場合の話です。
# 保証されているという記述をMSDNなどで見つけることができれば
# 全く問題ないですし、「この方法で取得できるよ、経験的に問題ないよ」
# という方がいれば、選択肢が増えますが。
たいちう様、回答ありがとうございます。
私が開発する範囲なら、面倒でもなんとかなるかと思います。
冒頭の質問のようにEXE側のみで対応が可能であるか否かを知りたいのです。
DLL側を修正すれば、対応可能であることは周知のことです。
そんな方法はないと言われれば、それまでですが。。。。
腕に自信があって面倒でも構わないならば、
CWinAppのダミーのインスタンスを持つexeをVC6で作り、
VC6のdllはこのexe経由で呼出し、
VC9のexeでこのインスタンスを更新・監視しておくとか、
バージョンの違いを吸収するdllをVC6で作ってラッパーにするとか、
元のdllに手を触れないで済ませる方法はあるでしょう。
よほどの事がない限り私はこんな選択はしませんが。
お望みの回答でなくて申し訳ないですが、私に言えるのはここまでです。
良い方法が見つかるといいですね。