wxDev.fr, le portail francophone consacré à wxWidgets ! ( The french portal for wxWidgets )  
Esp. membre
Recheche rapide



Recherche avancée
Statistiques
Membres inscrits :2359

Membres en ligne : 0
Invités en ligne : 3

Valid XHTML 1.0 Transitional

Valid CSS2

Menu forum (navigation):
Pages: 1  
 
Accueil » Accueil forums » Utilisation générale wxWidgets
» Plugins + Events persos
Conversation (Résolue) : Plugins + Events persos
16-01-2012 22:29:20  Plugins + Events persos #1
dragonjoker (Nouveau membre)
Lieu: Bras d'Asse (04)
Inscrit le : 16-01-2012
Messages: 9
Snippets: 0
Tutoriels: 0
Site web
Hors ligne
Bonjour à vous !

Je me pose une question due à des problèmes que je rencontre :
Quelle est la bonne méthode pour déclarer un évènement personnalisé dans une lib statique, sachant que cet event peut être utilisé conjointement dans des lib dynamiques et dans un exe.

J'ai en effet une application qui charge des plugins, la communication entre eux se fait via des évènements. J'ai créé une lib contenant la base commune à ces plugins et à cette application.

Les problèmes que je rencontre sont au nombre de 2, et sous linux seulement :
- IMPLEMENT_DYNAMIC_CLASS lève des assertions à l'initialisation des plugins (il est apparemment lancé une fois par plugin, pas trop intéressant, en fait ^^' )
- La MainFrame ne passe pas dans la fonction de traitement de l'évènement, ce malgré le fait qu'il soit apparemment bien ajouté à sa pile d'évènements.

J'ai créé mon event de la manière suivante:

Code wxWidgets:

//StatusUpdateEvent.h
namespace ProceduralTextures
{
    extern const wxEventType wxEVT_STATUS_UPDATE;
    class wxStatusUpdateEvent : public wxNotifyEvent
    {
    private:
        wxMilliClock_t m_savedTime;
        wxMilliClock_t m_time;
        int m_iIndex;
 
    public:
        wxStatusUpdateEvent( int p_iIndex=0, int p_winid=wxID_ANY );
        wxStatusUpdateEvent( const wxStatusUpdateEvent & p_event );
 
        virtual wxEvent * Clone() const;
        void ResetTime();
 
        inline wxMilliClock_t    GetTime        ()const    { return m_time; }
        inline int        GetIndex    ()const    { return m_iIndex; }
 
        DECLARE_DYNAMIC_CLASS( wxStatusUpdateEvent )
    };
}


Code wxWidgets:

// StatusUpdateEvent.cpp
#include "StatusUpdateEvent.h"
 
#ifdef __WXMSW__
#    include<wx/msw/msvcrt.h>
#endif
 
using namespace ProceduralTextures;
 
const wxEventType ProceduralTextures::wxEVT_STATUS_UPDATE = wxNewEventType();
 
IMPLEMENT_DYNAMIC_CLASS( wxStatusUpdateEvent, wxNotifyEvent )
 
wxStatusUpdateEvent :: wxStatusUpdateEvent( int p_iIndex, int p_winid )
    :    wxNotifyEvent( wxEVT_STATUS_UPDATE )
    ,    m_time( 0 )
    ,    m_savedTime( wxGetLocalTimeMillis() )
    ,    m_iIndex( p_iIndex )
{
}
 
wxStatusUpdateEvent :: wxStatusUpdateEvent( const wxStatusUpdateEvent & p_event )
    :    wxNotifyEvent( p_event )
    ,    m_time( p_event.m_time )
    ,    m_savedTime( p_event.m_savedTime )
    ,    m_iIndex( p_event.m_iIndex )
{
}
 
void wxStatusUpdateEvent :: ResetTime()
{
    m_time = wxGetLocalTimeMillis() - m_savedTime;
    m_savedTime = wxGetLocalTimeMillis();
}
 
wxEvent * wxStatusUpdateEvent :: Clone() const
{
    return new wxStatusUpdateEvent( * this );
}


Mes plugins sont définis de la manière suivante :

Code Cpp:

// Plugin.h
#if ! defined( _WIN32 )
#define DECLARE_PLUGIN() virtual void Destroy();
#define IMPLEMENT_PLUGIN( plugin, panel, generator)    extern "C" PluginBase * CreatePlugin( wxDynamicLibrary * p_pDll) { return new plugin(); }\
                                                        void plugin::Destroy(){ delete this; }
#else
#include <process.h>
#define DECLARE_PLUGIN() virtual void Destroy();
#define IMPLEMENT_PLUGIN( plugin, panel, generator)    HANDLE Plugin<panel, generator, plugin>::m_hThreadId = NULL;\
                                                        wxCriticalSection Plugin<panel, generator, plugin>::m_critStartup;\
                                                        wxDynamicLibrary * Plugin<panel, generator, plugin>::m_pDll = NULL;\
                                                        extern "C"\
                                                        {\
                                                            __declspec( dllexport) PluginBase * CreatePlugin( wxDynamicLibrary * p_pDll){ return Plugin<panel, generator, plugin>::Creator( p_pDll); }\
                                                            __declspec( dllexport) void DestroyPlugin() { Plugin<panel, generator, plugin>::Destroyer(); }\
                                                        }\
                                                        IMPLEMENT_APP_NO_MAIN( plugin)\
                                                        void plugin::Destroy()\
                                                        {\
                                                            DestroyPlugin();\
                                                        }
#endif
 
namespace ProceduralTextures
{
    class ProceduralGenerator;
    template <class PanelClass, class GeneratorClass, class PluginClass> class Plugin;
    class PluginBase;
    class ConfigPanel;
 
    //! Plugin base class
    /*!
    Under MS Windows, in order to have access to every dynamic wxWidget class,
    we must instantiate a winapp for each dll loaded. So plugin extends wxApp and lauches a dllmain.
    It causes troubles with OpenGL, which functions must be loaded in each main, so OpenGL functions
    are loaded in each procedural generator, instead of being loaded in the main application.
    \author Sylvain DOREMUS
    \version 1.2.0.0
    \date 01/07/2011
    */

    class PluginBase
#if defined( _WIN32 )
        :   public wxApp
#endif
    {
    public:
        PluginBase();
        virtual ~PluginBase();
 
        virtual void Destroy()=0;
 
        virtual ProceduralGenerator * CreateGenerator( int p_iWidth, int p_iHeight, int p_iWndId, wxFrame * p_pFrame)=0;
        virtual void DestroyGenerator()=0;
        virtual wxString GetName()=0;
 
        virtual void CreateConfigPanel( wxWindow * p_pParent)=0;
        virtual void InitConfigPanel( const wxPoint & p_ptPosition, const wxSize & p_size)=0;
        virtual ConfigPanel * GetConfigPanel()const=0;
        virtual void DestroyConfigPanel()=0;
    };
 
    template <class PanelClass, class GeneratorClass, class PluginClass>
    class Plugin : public PluginBase
    {
    protected:
        PanelClass        *    m_pConfigPanel;
        GeneratorClass    *    m_pGenerator;
 
#if defined( _WIN32 )
    private:
        static wxCriticalSection    m_critStartup;
        static HANDLE                m_hThreadId;
        static wxDynamicLibrary    *    m_pDll;
 
        typedef enum
        {    eTerminate
        }eIDs;
 
        static unsigned wxSTDCALL Launcher(void * p_event)
        {
#    if wxVERSION_NUMBER < 2900
            const HINSTANCE l_hInstance = m_pDll->GetLibHandle();
#    else
            const HINSTANCE l_hInstance = wxDynamicLibrary::MSWGetModuleHandle( "", & Plugin<PanelClass, GeneratorClass, PluginClass>::m_hThreadId);
#    endif
 
            if ( ! l_hInstance )
            {
                return 0;
            }
 
#    if wxVERSION_NUMBER >= 2900
            wxDISABLE_DEBUG_SUPPORT();
#    endif
            wxInitializer l_wxinit;
 
            if ( ! l_wxinit.IsOk() )
            {
                return 0;
            }
 
            HANDLE l_hEvent = *(static_cast<HANDLE *>(p_event));
 
            if ( ! SetEvent( l_hEvent) )
            {
                return 0;
            }
 
            wxEntry( l_hInstance);
            return 1;
        }
 
    public:
        static PluginBase * Creator( wxDynamicLibrary * p_pDll)
        {
            wxCriticalSectionLocker lock( m_critStartup);
 
            if ( ! m_hThreadId )
            {
                m_pDll = p_pDll;
                HANDLE l_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
 
                if ( ! l_hEvent )
                {
                    return NULL;
                }
 
                m_hThreadId = (HANDLE)_beginthreadex( NULL, 0, & Launcher, & l_hEvent, 0, NULL );
 
                if ( ! m_hThreadId )
                {
                    CloseHandle( l_hEvent);
                    return NULL;
                }
 
                WaitForSingleObject( l_hEvent, INFINITE);
                CloseHandle( l_hEvent);
            }
 
            return (PluginBase *)wxApp::GetInstance();
        }
        static void Destroyer()
        {
            wxCriticalSectionLocker lock( m_critStartup);
 
            if ( ! m_hThreadId )
            {
                return;
            }
 
            m_pDll->Detach();
            delete m_pDll;
 
            wxThreadEvent * l_pEvent = new wxThreadEvent( wxEVT_THREAD, eTerminate);
            wxTheApp->AddPendingEvent( * l_pEvent);
 
            // We must then wait for the thread to actually terminate.
            WaitForSingleObject( m_hThreadId, INFINITE);
            CloseHandle( m_hThreadId);
            m_hThreadId = NULL;
            delete l_pEvent;
        }
        void OnTerminate( wxThreadEvent & event)
        {
            ExitMainLoop();
        }
#endif
    public:
        Plugin()
            :    PluginBase()
            ,    m_pConfigPanel    ( NULL)
            ,    m_pGenerator    ( NULL)
        {
#if defined( _WIN32 )
            Connect( eTerminate, wxEVT_THREAD, wxThreadEventHandler( Plugin::OnTerminate));
#endif
        }
        virtual ~Plugin()
        {
        }
        ProceduralGenerator * CreateGenerator( int p_iWidth, int p_iHeight, int p_iWndId, wxFrame * p_pFrame)
        {
            DestroyGenerator();
            m_pGenerator = new GeneratorClass( p_iWidth, p_iHeight, p_iWndId, p_pFrame);
            return m_pGenerator;
        }
        void DestroyGenerator()
        {
            delete m_pGenerator;
            m_pGenerator = NULL;
        }
        void CreateConfigPanel( wxWindow * p_pParent)
        {
            m_pConfigPanel = new PanelClass( p_pParent, wxID_ANY, wxDefaultPosition, wxDefaultSize);
        }
        void InitConfigPanel( const wxPoint & p_ptPosition, const wxSize & p_size)
        {
            m_pGenerator->SetConfigPanel( m_pConfigPanel);
            m_pConfigPanel->Create( m_pGenerator, m_pConfigPanel->GetParent(), p_ptPosition, p_size);
            m_pConfigPanel->Show();
        }
        ConfigPanel * GetConfigPanel()const
        {
            return m_pConfigPanel;
        }
        void DestroyConfigPanel()
        {
            if (m_pConfigPanel != NULL)
            {
                m_pConfigPanel->Close();
                delete m_pConfigPanel;
                m_pConfigPanel = NULL;
            }
        }
        bool OnInit()
        {
            return true;
        }
        int OnExit()
        {
            return 0;
        }
    };
 
    typedef PluginBase * (CreatePluginFunction)( wxDynamicLibrary * p_pDll);
    typedef CreatePluginFunction * PCreatePluginFunction;
}
17-01-2012 00:35:08  Re: Plugins + Events persos #2
Xaviou (Administrateur)
Lieu: Annecy (74)
Inscrit le : 27-08-2007
Messages: 1387
Snippets: 25
Tutoriels: 6
Site web
Hors ligne
Salut.

Je n'ai pas regardé tout le code en détail, mais voici déjà une piste.

En fait, comme tu utilises une lib statique, chaque module (exe ou plugin) l'utilisant va avoir sa propre version, et du coup, la constante wxEVT_STATUS_UPDATE sera différente pour chacun d'eux.

Pour ma part, dans ce cas, (voir les sources de wxToDoList), je crée la valeur une seule fois, et je la passe en paramètre au plugin lors de sa création (lors de la création du wxPanel d'affichage en vérité, mais c'est pareil).
Ainsi, c'est bien la même valeur utilisée par les plugins et l'exécutable.

@+
Xav'

Le nouveau portail wxWidgets francophone : www.wxdev.fr
Ben en fait, vous y êtes déjà... et effectivement, depuis le temps, ce n'est plus tellement nouveau....
17-01-2012 21:18:31  Re: Plugins + Events persos #3
dragonjoker (Nouveau membre)
Lieu: Bras d'Asse (04)
Inscrit le : 16-01-2012
Messages: 9
Snippets: 0
Tutoriels: 0
Site web
Hors ligne
OK !
Bon, ça marche effectivement comme ça, j'ai en plus enlevé les lignes DECLARE_DYNAMIC_CLASS... et IMPLEMENT_DYNAMIC_CLASS... pour l'assertion.
Je verrai plus tard sous Windows ce que ça donne, ça fonctionne en tout cas sous Linux.
Menu forum (navigation):
Pages: 1  
 
Accueil » Accueil forums » Utilisation générale wxWidgets
» Plugins + Events persos