2011-12-14 26 views
4

私はMFCと戦い、DLLをLoadLibraryと動的にリンクしています。私は、アプリケーションがDLLを呼び出すと、MFCの状態を取得することができないと思われ、DLLは同じ呼び出しでコールバックします。最終的に、それは数多くの主張につながる。DLLがLoadLibraryを通じて呼び出されたときにMFCの状態が無効になる

ここでは、私がやっていることのコードモックアップです。

  1. アプリケーションは、ウィザードMFCアプリからまっすぐです。私はどこかのボタンを持っているし、これは、ボタンのハンドラである:

    void callback() 
    { 
        AFX_MANAGE_STATE(AfxGetStaticModuleState()); 
    
        CDialog1 dlg; 
        dlg.DoModal(); 
    } 
    
    typedef void (*TPluginMainFunc)(void*); 
    
    void CTheApp1View::OnTestRun1() 
    { 
         static HMODULE hPluginMFCShared = LoadLibrary(_T("PluginMFCShared")); 
         if (hPluginMFCShared) 
         { 
           TPluginMainFunc func = (TPluginMainFunc) GetProcAddress(hPluginMFCShared, "plugin_main"); 
           if (func) 
           { 
             func(callback); 
           } 
         } 
    } 
    
  2. 次に「PluginMFCShared」は次のようになります。

    typedef void (*TFunc)(); 
    
    extern "C" void GS_EXTERNAL_ENTRY plugin_main(TFunc func) 
    { 
         AFX_MANAGE_STATE(AfxGetStaticModuleState()); 
    
         func(); 
    
         CDialog1 dlg; 
         dlg.DoModal(); 
    } 
    

ので、アイデアがあることアプリです(CTheApp1View :: OnTestRun1)は、ライブラリをロードし、コールバックポインタを直接渡す関数を呼び出します。ライブラリはそのコールバックを使用して、アプリケーションから何かを実行してから続行します。

私はAFX_MANAGE_STATEがMFC状態を処理すると思っていましたが、それ以上の処理が必要なようです。 SystemOfPlugins.zip

任意のアイデア:

テストプロジェクトは、(TheApp1プロジェクトが立ち上げたプロジェクトに設定されていることを確認してください)で発見されるだろうか?

ありがとうございます。

+0

DLLial、アプリケーション、またはその両方でCDialog1が定義されていますか?両方の場所で使用しているように見えますが、これは問題になります。 'DoModal'はどこに定義されていても必要です。 –

+0

はい、CDialog1は、アプリケーションとDLLで別々に定義されており、全く異なるダイアログリソースです。 2つのプロジェクト(アプリケーションとDLL)には何も共通点がありません。コードスニペットは、その事例を示すためのものです。 –

答えて

2
後の1をポップ

別の提案があります。アプリの変数では、AFX_MODULE_STATE *という名前の変数m_pModuleStateを追加し、InitInstance関数のfuncitonの最後でそれを初期化し、

m_pModuleState = AfxGetModuleState(); 

がダイアログを開く前に、アプリケーションの状態を設定するためのコールバック関数を変更し、バック設定それはあなたの例

extern "C" void GS_EXTERNAL_ENTRY plugin_main(TFunc func) 
{ 
    AFX_MANAGE_STATE(AfxGetStaticModuleState()); 

    func(); 
    CDialog1 dlg; 
    dlg.DoModal(); 
} 

このやり方をしていたとして機能

void callback() 
{ 
    //Get the original state 
    AFX_MODULE_STATE* pOriginalState = AfxGetModuleState(); 

    //Set the mfc state 
    AfxSetModuleState(((CTheApp1App*)&theApp)->m_pModuleState); 

    //Do stuff here 
    CDialog1 dlg; 
    dlg.DoModal(); 

    //Set the mfc state back to its original state 
    AfxSetModuleState(pOriginalState); 
} 

そして、あなたのプラグインを保つを終了する前に元の状態、あなたは呼ぶだろうA FX_MANAGE_STATEをプラグインで使用していますが、プラグインの一部がコールバック関数を呼び出すときに、適切なダイアログリソースを見つけて状態固有の関数を実行できるようにアプリケーションの状態を設定してください。

+0

私はあなたに解決策を試しました、そして、それは正常に動作します、それはリソースの問題を解決します。しかし、それ以上のことがあるようですが、他のMFC機能を使用しようとすると、同様の理由で失敗します。MFCの '状態'に問題があります。 –

+0

ああ、申し訳ありませんが、私は以前のコメントを早めに投稿しました。私は質問から元のサンプルを更新しました。リソースを修正する変更を適用しましたが、MFCのDYNAMIC_DOWNCASTを使用するもう1つの関数 'GetMainFrame'を追加しました。この関数が 'OnTestRun1'で使用されていれば正常に動作しますが、 'callback'で使用されている場合はそうではありません。クラス階層を解決できません。 –

+0

私は自分の答えを改善しました。リソースの状態だけを変更するのではなく、mfcモジュールの状態全体を変更します。これはあなたの問題を修正するはずです – Goldorak84

0

私はあなたのコードを見て、私はそれが2つの機能変性することにより、作業ました:pluginMFCShared.cppに

を、私はtheapp1view.cppで

extern "C" void GS_EXTERNAL_ENTRY plugin_main(TFunc func) 
{ 

    func(); 

    AFX_MANAGE_STATE(AfxGetStaticModuleState()); 
    CDialog1 dlg; 
    dlg.DoModal(); 
} 

)FUNCの呼び出し(後AFX_MANAGE_STATEと呼ばれます、私は

void callback() 
{ 
    CDialog1 dlg; 
    dlg.DoModal(); 
} 

今AFX_MANAGE_STATEを削除し、2つのダイアログは、別の

+0

答えをありがとう、それは問題を解決します。しかし、これは簡単な例です。実際には、このアプリケーションは一連のコールバック関数を提供しており、 'plugin_main'はいつでもコールバックを実行できるので、状態を定義するのはそれほど簡単ではありません。この場合、MFCの状態を管理する最も良い方法は何ですか。 –

0

dll _LIBプリプロセッサフ​​ラグ?もしそうなら、本当にすべきかどうかを確認してください - 'MFC dll'のコンセプト全体が陳腐化しているので、もう使用する理由はありません。その後、すべてのAFX_MANAGE_STATEのことを忘れてしまいます。 dllでは、DllMainに渡されるdllのHMODULEを格納し、CDialogなどを使用する前に、:: AfxSetResourceHandle()を正しい値に設定します。正しいリソースハンドルを設定し、オブジェクトがスコープから外れたときにそれを古いもの(メインアプリケーションのもの、通常は0x4000 ...)にリセットする、スマートなポインタのようなクラスに入れてください。

リソースハンドル(LoadStringなど)を直接渡すことができるすべての目的で、グローバルハンドルに触れる必要はありません。

作業がずっと簡単で、はるかに透過的です。リソースハンドルは、VS6以降のMFCバージョンのMFC状態に関係する唯一のものです。

+0

いいえ、私は_USRDLLでコンパイルしています。 –

+0

はい、申し訳ありませんが、それは私が意味するものです。 AFX_MANAGE_STATEの内容全体をダンプするだけで、不必要に複雑になります(2011年)。 – Roel

関連する問題