Membres inscrits :611
Membres en ligne : 0
Invités en ligne : 8


|
| Conversation (Résolue) : Plugins + Events persos |
dragonjoker (Nouveau membre)
Lieu: Bras d'Asse (04)
Inscrit le : 16-01-2012
Messages: 6
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; }
| |
|
Xaviou (Administrateur)
Lieu: Annecy (74)
Inscrit le : 27-08-2007
Messages: 1154
Snippets: 23
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à...
|
dragonjoker (Nouveau membre)
Lieu: Bras d'Asse (04)
Inscrit le : 16-01-2012
Messages: 6
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.
| |
|
|