IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

wxWidgets Discussion :

wxMessageBox ou wxDialog dans une DLL


Sujet :

wxWidgets

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 81
    Points : 51
    Points
    51
    Par défaut wxMessageBox ou wxDialog dans une DLL
    Bonjour,

    Je développe une DLL qui doit, à partir d'une fonction globale, fournir une fenetre de dialogue

    Pour l'instant j'arrive à appeller ma fonction globale dans ma DLL

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void MyFrame::OnMenuCommand(wxCommandEvent& WXUNUSED(event))
    {
      // Load up the DLL
      HMODULE hModule = LoadLibrary(_T("maDll.dll"));
      HWND hWnd =(HWND)this->GetHandle();
     
      // Call function in DLL
      DLLTotoPtr pProc = (DLLTotoPtr)GetProcAddress(hModule,_T("DLLToto"));
      (pProc)(hWnd);
      FreeLibrary(hModule);
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    extern "C" IMPORT_EXPORT void DLLToto(HWND handle)
    {
            wxWindow win;
            win.SetHWND((WXHWND)handle);
            win.Enable(false);
     
            wxDialog dlg(&win, -1, wxT("wxDialog in DLL"), wxDefaultPosition, wxSize(150,150));
            dlg.ShowModal(); // <- plantage à cette ligne
     
            win.Enable(true);
            win.SetHWND(0);
    }
    Mais lorsque j'essaye d'afficher un wxMessageBox ou un wxDialog à partir de ma fonction globale dans ma DLL, j'obtiens une erreur à l'execution
    "le programme appellant à généré un point d'arrêt"
    le debbuger fournti l'explication suivante :
    assert "wxThread::IsMain()" failed in wxMutexGuiLeaveOrEnter(): only main thread may call wxMutexGuiLeaveOrEnter()! [in child thread]
    ACCallDll.exe a déclenché un point d'arrêt
    Cette erreur d'execution ne se produit pas si je n'appelle pas de fenetre
    Et je n'y comprends rien ...
    Merci de votre aide

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour,
    L'erreur que tu indiques semble plus liée à un appel dans un thread différent que dans une DLL. wxWidgets (et l'API native windows sous-jacente) n'aime pas trop l'appel de fonctions I.H.M. dans des threads différents du thread principal :
    wxWidgets calls in secondary threads
    All threads other then the "main application thread" (the one wxApp::OnInit or your main function runs in, for example) are considered "secondary threads". These include all threads created by wxThread::Create or the corresponding constructors.

    GUI calls, such as those to a wxWindow or wxBitmap are explicitly not safe at all in secondary threads and could end your application prematurely. This is due to several reasons, including the underlying native API and the fact that wxThread does not run a GUI event loop similar to other APIs as MFC.

    A workaround that works on some wxWidgets ports is calling wxMutexGUIEnter before any GUI calls and then calling wxMutexGUILeave afterwords. However, the recommended way is to simply process the GUI calls in the main thread through an event that is posted by either wxPostEvent or wxEvtHandler::AddPendingEvent. This does not imply that calls to these classes are thread-safe, however, as most wxWidgets classes are not thread-safe, including wxString.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 81
    Points : 51
    Points
    51
    Par défaut
    En reprenant l'exemple à partir duquel je construis mon projet,
    j'ai donc ajouté le code suivant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    // We use IMPLEMENT_APP_NO_MAIN so we can start the app from DllMain
    // as we don't have a WinMain or main entry point
    IMPLEMENT_APP_NO_MAIN(MyDllApp)
    Pour obtenir un point d'entrée dans ma DLL
    code.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #ifdef __WXMSW__ 
    // Define a new application type, each program should derive a class from wxApp
    class MyDllApp : public wxApp
    {
    public:
        // override base class virtuals
        // ----------------------------
        // this one is called on application startup and is a good place for the app
        // initialization (doing it here and not in the ctor allows to have an error
        // return: if OnInit() returns false, the application terminates)
        virtual bool OnInit();
    };
    #endif
    code.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    HANDLE ThreadId;
    MyDllApp *maDll=NULL;
     
    DWORD WINAPI ThreadProc(LPVOID lpParameter)
     {
    int argc=0;
    char **argv=NULL;
    wxApp::SetInstance(maDll=new MyDllApp());
    wxEntryStart(argc,argv);
    MyDllApp *g=(MyDllApp*)maDll;
    g->OnInit();
    g->OnRun();
    return true;
     }
     
    // We use IMPLEMENT_APP_NO_MAIN so we can start the app from DllMain
    // as we don't have a WinMain or main entry point
    IMPLEMENT_APP_NO_MAIN(MyDllApp)
     
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved )
    {
        switch (ul_reason_for_call)
        {
            case DLL_PROCESS_ATTACH:
                ThreadProc((void*)NULL);
            break;
            case DLL_THREAD_ATTACH:
            break;
            case DLL_THREAD_DETACH:
            break;
            case DLL_PROCESS_DETACH:
                 wxEntryCleanup();
            break;
        }
        return TRUE;
    }
    Le code s'execute (presque) correctement
    J'imagine que sans cette ligne de code magique
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IMPLEMENT_APP_NO_MAIN(MyDllApp)
    il y avait deux points d'entrée concurrents

Discussions similaires

  1. [MDI][DLL] Enfant MDI dans une dll
    Par Pascal Jankowski dans le forum Composants VCL
    Réponses: 5
    Dernier message: 02/04/2004, 07h41
  2. [VStudio 6] pb avec fonctions dans une DLL
    Par MogDeChNord dans le forum MFC
    Réponses: 8
    Dernier message: 08/01/2004, 08h57
  3. [BP7] Problème chargement de ressource dans une DLL
    Par Alcatîz dans le forum Turbo Pascal
    Réponses: 11
    Dernier message: 26/07/2003, 21h36
  4. PB avec "self" dans une dll
    Par DiJiRiDouS dans le forum Langage
    Réponses: 2
    Dernier message: 21/02/2003, 09h32
  5. [VB6]Passage d'un tableau dans une DLL écrite en delphi
    Par flash dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 20/09/2002, 10h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo