Plugin oriented App Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
jfouche
Super wx Problem Solver
Super wx Problem Solver
Posts: 442
Joined: Tue May 06, 2008 4:52 pm
Location: France

Post by jfouche »

Do not use DECLARE_EVENT_TYPE and DEFINE_EVENT_TYPE with plugins. You must explicit the ID. I personnaly use enum in a
common header.
Jérémie
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

jfouche wrote:Do not use DECLARE_EVENT_TYPE and DEFINE_EVENT_TYPE with plugins. You must explicit the ID. I personnaly use enum in a
common header.
Ah, I don't use them but I wanted to know how I can generate Unique IDs so that No two plugins will have same Id? Should I use wxWindow::GetId() in Connecting events or what? :roll:

Could you provide example how you do with two plugins (Only ID section) Because AFAIK two diferent Enum can have same numerical value.
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
jfouche
Super wx Problem Solver
Super wx Problem Solver
Posts: 442
Joined: Tue May 06, 2008 4:52 pm
Location: France

Post by jfouche »

Excuse me, I didn't read carefuly...
Can you provide a small example (by text), because I don't see the problem.
Jérémie
User avatar
xaviou
Super wx Problem Solver
Super wx Problem Solver
Posts: 437
Joined: Mon Aug 21, 2006 3:18 pm
Location: Annecy - France
Contact:

Post by xaviou »

Hi
evstevemd wrote:Now that I can load Menus from DLL to App, I have question:
We know events are generated by App Menu and are connected to Specific wxID. So How do I ensure there is no ID conflict within plugins and that I have Unique ID?
You should use the wxNewId() and wxNewEventType() functions, so, you'll be sure that your IDs will be unique ones.
evstevemd wrote:Should I use wxWindow::GetId() in Connecting events or what?
That's (I think) the good way to do it.

Regards

Xav'
My wxWidgets stuff web page : X@v's wxStuff
jfouche
Super wx Problem Solver
Super wx Problem Solver
Posts: 442
Joined: Tue May 06, 2008 4:52 pm
Location: France

Post by jfouche »

xaviou wrote:You should use the wxNewId() and wxNewEventType() functions, so, you'll be sure that your IDs will be unique ones.
I don't think so. In the application you'll have an instance of the static var which auto generate the IDs. In the plugin, you'll have another one. So you can have multiple IDs with the same values, even if you use wxNewId(). (I experienced it recently).

That's why I was talking about a unique common header file describe explicitly the available ID for events.
For the controls, I don't think there is problems, but I'm waiting for somebody to tell me I'm wrong :wink:
Jérémie
User avatar
xaviou
Super wx Problem Solver
Super wx Problem Solver
Posts: 437
Joined: Mon Aug 21, 2006 3:18 pm
Location: Annecy - France
Contact:

Post by xaviou »

Hi
jfouche wrote:
xaviou wrote:You should use the wxNewId() and wxNewEventType() functions, so, you'll be sure that your IDs will be unique ones.
I don't think so. In the application you'll have an instance of the static var which auto generate the IDs. In the plugin, you'll have another one. So you can have multiple IDs with the same values, even if you use wxNewId(). (I experienced it recently).
I've just tested it, and Ids are uniques :

I have a host app, and a dll plugin.
The host app has a wxNoteBook : the first page is generated by the exe itself, and the other pages (only one, in the test), are generated by the plugins.
On both pages, I've put a button with the following code :

Code: Select all

void MainFrame::OnTest(wxCommandEvent &event)
{
    int id=wxNewId();
    wxString sMsg;
    sMsg.Printf(_T("New Id generated = %0d"), id);
    wxMessageBox(sMsg);
}

[code]void PluginPanel::OnButtonClicked(wxCommandEvent &event)
{
	static int i=0;
	i++;
	m_stBox->SetLabel(wxString::Format(_T("Click #%0d"),i));
	int id=wxNewId();
    wxString sMsg;
    sMsg.Printf(_T("New Id generated = %0d"), id);
    wxMessageBox(sMsg);
}

[/code]

If I press 2 times the "frame" button, I get the IDs "100" then "101"
Then, I press the "Plugin" button, and I get the ID "102"
If I come back to the frame button, I get "103", and so on.

As both the plugins and the host application use the dynamic version of the libs (if not, it won't work), the static var used is the same.


But I've just read something in the 2.9.1's doc : wxNewId and wxNewEventType will be deprecated, because they can conflict with IDs defined by the user code.
wxID_ANY is strongly recommended.

Regards

Xav'
My wxWidgets stuff web page : X@v's wxStuff
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

Thanks guys,
I think I will go for wxID_ANY and wxWindow::GetId(). If I will need cleaner code I will go for Jeremie's dedicated header with enum.
Thanks again guys :)
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

Hi Friends, I have faced the code I cannot understand.

Code: Select all

wxClassInfo::sm_classTable->BeginFind();

I checked the Manual and Couldn't find anything. Is it hidden somewhere?
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
User avatar
xaviou
Super wx Problem Solver
Super wx Problem Solver
Posts: 437
Joined: Mon Aug 21, 2006 3:18 pm
Location: Annecy - France
Contact:

Post by xaviou »

Hi.

This is part of the undocumented wxWidgets stuff :wink:

As I understood, the library has a static list of all dynamically registered classes (the ones whitch use the DECLARE_DYNAMIC_CLASS and IMPLEMENT_DYNAMIC_CLASS macros) : the name of this list is sm_classTable.

The code you pointed allow an interation into this list.

With wxWidgets-2.9.1, this code won't work, as the sm_classTable becomes private.

Regards

Xav'
My wxWidgets stuff web page : X@v's wxStuff
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

xaviou wrote:Hi.

This is part of the undocumented wxWidgets stuff :wink:

As I understood, the library has a static list of all dynamically registered classes (the ones whitch use the DECLARE_DYNAMIC_CLASS and IMPLEMENT_DYNAMIC_CLASS macros) : the name of this list is sm_classTable.

The code you pointed allow an interation into this list.

With wxWidgets-2.9.1, this code won't work, as the sm_classTable becomes private.

Regards

Xav'
i appreciate your ready help, sir. So then in future this technique will be having a problem! What methods can you and anyone propose? What about making extern C methods for exporting the class...just to hear your thought guys and girls on this.

Again, thanks
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
User avatar
xaviou
Super wx Problem Solver
Super wx Problem Solver
Posts: 437
Joined: Mon Aug 21, 2006 3:18 pm
Location: Annecy - France
Contact:

Post by xaviou »

Hi

I've already tested, for the wxWidgets-2.9.1 migration of my app.

The sm_classTable becomes private, but new members are created (in <wx/object.h> of the wx-2.9.1 includes) :
  • static const_iterator begin_classinfo();
  • static const_iterator end_classinfo()
So, the (simplified) code

Code: Select all

wxHashTable_Node* node;
wxClassInfo::sm_classTable->BeginFind();
while((node = wxClassInfo::sm_classTable->Next()))
{
    wxClassInfo *classInfo = (wxClassInfo *)node->GetData();
    wxString classname = classInfo->GetClassName();
    if(classname.StartsWith(_T("wxTdlPlugin_")))
    {
        PluginBase *object = (PluginBase*)classInfo->CreateObject();
        m_plugins.Add(object);
    }
}
will become :

Code: Select all

wxClassInfo::const_iterator iter;
for (iter=wxClassInfo::begin_classinfo(); iter!=wxClassInfo::end_classinfo(); iter++)
{
    const wxClassInfo *classInfo = *iter;
    wxString classname = classInfo->GetClassName();
    if(classname.StartsWith(_T("wxTdlPlugin_")))
    {
        PluginBase *object = (PluginBase*)classInfo->CreateObject();
        m_plugins.Add(object);
    }
}
Regards
Xav'
My wxWidgets stuff web page : X@v's wxStuff
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

xaviou wrote:Hi

I've already tested, for the wxWidgets-2.9.1 migration of my app.

The sm_classTable becomes private, but new members are created (in <wx/object.h> of the wx-2.9.1 includes) :
  • static const_iterator begin_classinfo();
  • static const_iterator end_classinfo()
So, the (simplified) code

Code: Select all

wxHashTable_Node* node;
wxClassInfo::sm_classTable->BeginFind();
while((node = wxClassInfo::sm_classTable->Next()))
{
    wxClassInfo *classInfo = (wxClassInfo *)node->GetData();
    wxString classname = classInfo->GetClassName();
    if(classname.StartsWith(_T("wxTdlPlugin_")))
    {
        PluginBase *object = (PluginBase*)classInfo->CreateObject();
        m_plugins.Add(object);
    }
}
will become :

Code: Select all

wxClassInfo::const_iterator iter;
for (iter=wxClassInfo::begin_classinfo(); iter!=wxClassInfo::end_classinfo(); iter++)
{
    const wxClassInfo *classInfo = *iter;
    wxString classname = classInfo->GetClassName();
    if(classname.StartsWith(_T("wxTdlPlugin_")))
    {
        PluginBase *object = (PluginBase*)classInfo->CreateObject();
        m_plugins.Add(object);
    }
}
Regards
Xav'
ahsante sana (thanks a lot)
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

I appreciate your help Xav and Jeremie I have come to the final part of my app (I halted for a time as I do this not as dedicated work, and time you knoq ;)). i have written Plugin interface and I'm about to write test plguin and then Manager. But I have question. In windows we need dllspec__ thing and I hope none in linux and I don't know in Mac. Is there a wx way to export plugins class from dll/so? How do you make a dll/so without doing changes to code?

I have searched forum and I have not found goog answe (may be i use bad leyword)

again, thanks alot for invaluable contributions
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
jfouche
Super wx Problem Solver
Super wx Problem Solver
Posts: 442
Joined: Tue May 06, 2008 4:52 pm
Location: France

Post by jfouche »

Hello

There are 2 great wx macros : WXEXPORT and WXIMPORT.
Have a look to this wiki. This works for Windows, MAC and Linux.

But, for a simple function export, I do the following :

Code: Select all

#ifdef _WIN32
	#define EXPORT  __declspec(dllexport)
#else
	#define EXPORT
#endif


extern "C" EXPORT IPlugin* GetPlugin(IManager* manager)
{
   ...
}
Jérémie
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2408
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania

Post by evstevemd »

that is great! Thank you!
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
Post Reply