Comincio con l'inaugurare questo blog con un primo argomento che a suo tempo mi fece perdere parecchio tempo. Parto subito con il dire che programmo in C da tantissimi anni mentre digerisco male la programmazione C++. Da un annetto ho cominciato ad usare le librerie wxwidgets e l'IDE CodeBlock per svincolarmi dall'ormai vecchio Borland C++ Builder e poter cominciare a fare una programmazione multiplatform dei miei progetti. Devo ammettere che l'impatto è stato molto duro e cose che con il Borland facevo in modo semplice ed intuitivo, ora sono diventati veri e propri incubi.
I primi problemi nascono quando comincio a "far sul serio" e decido di convertire il software che stavo sviluppando per controllare l'impianto domotico di casa. Mi ritrovo a gestire i thread (wxThread) e, cosa che mi ha fatto impazzire, la creazione di wxEvent custom per permettermi di scambiare dati fra il thread principale del programma ed i thread secondari. La cosa bizzarra era peraltro che se facevo un progetto su un'unico file, anche se dopo numerosi tentativi, il tutto funzionava ma non riuscivo in alcun modo a portare il codice che gestiva gli eventi customizzati in un file separato....
Eccovi perciò un listato diviso in 4 files con tutto il necessario. Da una parte i frammenti dell'applicazione principale (labmain) e dall'altra il file che contengono la definizione sia del thread che dell'evento custom (sys). Abbiate pazienza ma non ho inserito gli include per il semplice motivo che non ricordo quali siano quelli fondamentali.
--------------------------------------------------------------------------------------------------
labmain.cpp
--------------------------------------------------------------------------------------------------
CustomThread * MyIPCServer=NULL;
labFrame::labFrame(wxWindow* parent,wxWindowID id)
{
.....
Connect( wxID_ANY, E_IPCEvent,MyIPCEventHandler(labFrame::DoIPCEvent), NULL, this );
....
}
....lancio del thread da inserire in una funzione qualsiasi....
MyIPCServer=new CustomThread(GetEventHandler());
if(!MyIPCServer) {...;return;}
if(MyIPCServer->Create((unsigned int)0)!=wxTHREAD_NO_ERROR) // lancia il thread che parte in modalità “suspended”. Lo 0 indica di usare lo stack di default
{
//ERROR
delete MyIPCServer;
return;
}
MyIPCServer->SetPriority(75); // setta la priorità del thread (da 0 a 100 dove lo 0 indica la priorità minore.
MyIPCServer->Run(); // questo lancia il thread*/
//thread is running
.....
void labFrame::DoIPCEvent(C_IPCEvent &event )
{
int ID=event.GetId();
if (ID>=IPCUserMessage && ID<=IPCFailure)
wxString Msg=event.GetText();
if (ID==SendUserMessage) ....;
else if (ID==SendError) ....;
else if (ID==SendDebug) ....;
else if (ID==SendVerbose) ....;
else if (ID==SendFailure) ....;
}
else ....;
//SendUserMessage = 1,SendWarning, SendError, SendDebug, SendVerbose
}
--------------------------------------------------------------------------------------------------
labmain.h
--------------------------------------------------------------------------------------------------
class labFrame: public wxFrame
{
....
void DoIPCEvent(C_IPCEvent &event );
....
}
--------------------------------------------------------------------------------------------------
sys.cpp
--------------------------------------------------------------------------------------------------
DEFINE_EVENT_TYPE(E_IPCEvent)
....
void CustomThread::SendThreadMessage(wxString str,int type)
{
if(EH)
{
C_IPCEvent event( E_IPCEvent, type );
event.SetText(str);
wxPostEvent( EH, event );
}
}
....
CustomThread::CustomThread(wxEvtHandler *ev): wxThread(wxTHREAD_JOINABLE)
{
EH=ev;
}
....
void* CustomThread::Entry()
{
SendThreadMessage(_("this is a message from a thread"),IPCDebug);
while(1)
{
if (TestDestroy())
{
....
break;
}
....
wxThread::Sleep(500);
}
}
--------------------------------------------------------------------------------------------------
sys.h
--------------------------------------------------------------------------------------------------
DECLARE_EVENT_TYPE( E_IPCEvent, -1 )
class C_IPCEvent: public wxCommandEvent
{
public:
C_IPCEvent( wxEventType commandType = E_IPCEvent, int id = 0 ) : wxCommandEvent(commandType, id) { }
wxEvent* Clone() const { return new C_IPCEvent(*this); }
wxString GetText() const { return m_Text; }
void SetText( const wxString& text ) { m_Text = text;}
private:
wxString m_Text;
};
typedef void (wxEvtHandler::*MyIPCEventFunction)(C_IPCEvent &);
#define MyIPCEventHandler(func) (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction) wxStaticCastEvent(MyIPCEventFunction, &func)
enum
{
IPCUserMessage = 1, IPCError, IPCDebug, IPCVerbose, IPCFailure
};
....
class CustomThread : public wxThread
{
public:
CustomThread(wxEvtHandler *);
~CustomThread();
void SendThreadMessage(wxString,int);
virtual void * Entry();
protected:
private:
wxEvtHandler * EH;
};
Spero che questo listato sia utile a tutti coloro che hanno disperatamente cercato una soluzione pronta al problema senza riuscire a trovarla.
Nessun commento:
Posta un commento