I've got myself a head-scratcher (at least for me ) here. I've written a DLL / SO that will be used by both wx and non-wx GUIs. To make it work with non-wx GUIs, I have a call to wxInitialize in the DLL / SO startup code. My problem is with wx GUIs. If the GUI is built in debug mode, it works correctly. If it is non-debug, the GUI will not start. If I remove the call to wxInitialize from the DLL / SO, the non-debug GUI works correctly. However, to support non-wx GUIs I must have the wxInitialize call. How do I handle this so I have only one DLL / SO to be used by both non-wx and wx GUIs?
I encountered this while testing on Ubuntu Feisty, but the final targets are both Linux and Windows XP. wxWidgets 2.8.3
Judy
dll for both wx and non-wx GUIs (no longer debug v optimized Topic is solved
dll for both wx and non-wx GUIs (no longer debug v optimized
Last edited by JudyL on Wed Sep 19, 2007 12:03 pm, edited 1 time in total.
DAMN! That only solved part of the problem. I've now got more info and it is no longer Platform Specific. I'll have to get the moderators to mark this NOT solved and move it out of Platform-related.
Details:
App # 1: Full wxGUI that uses both my DLL / SO and the wxWidgets DLL / SO. This app is derived from wxApp and includes DECLARE_APP and IMPLEMENT_APP.
App # 2: Full wxGUI that only uses the wxWidgets DLL / SO. This app is derived from wxApp and includes DECLARE_APP and IMPLEMENT_APP.
App # 3: Console app that uses both my DLL / SO and the wxWidgets DLL / SO. This app does not implement a wxApp of any sort. It uses wxInitialize only, called from main.
My DLL / SO: loaded library that uses the wxWidgets DLL / SO. It also does not implement a wxApp of any sort. It calls wxInitialize from its DllMain (PROCESS_ATTACH) / __attribute__ ((constructor)) MyDllInit function.
All wxWidgets compile flags are the same for both Windows XP using VS2005 and Ubuntu Feisty using KDevelop.
apps:
__WXGTK__ or __WXMSW___
WXUSINGDLL
DLL / SO:
__WXGTK__ or __WXMSW___
WXUSINGDLL
_USRDLL (Visual Studio only)
wxUSE_GUI=0
wxWidgets DLL / SO built for Linux with --enable-shared --enable-monolithic --with-gtk and for windows from the command line with SHARED=1 MONOLITHIC=1
Both app # 2 and app # 3 run correctly on both OSes. App # 1 fails the same on both OSes - it hits the ASSERT on line 65 on /src/common/init.cpp. I've attached the screen shot from the assertion on windows. I don't understand why it's down into the wxDummyConsoleApp class since this is not a console app. If I remove the wxInitialize from my DLL/ SO, all 3 apps run fine.
App 1:
DLL / SO:
Details:
App # 1: Full wxGUI that uses both my DLL / SO and the wxWidgets DLL / SO. This app is derived from wxApp and includes DECLARE_APP and IMPLEMENT_APP.
App # 2: Full wxGUI that only uses the wxWidgets DLL / SO. This app is derived from wxApp and includes DECLARE_APP and IMPLEMENT_APP.
App # 3: Console app that uses both my DLL / SO and the wxWidgets DLL / SO. This app does not implement a wxApp of any sort. It uses wxInitialize only, called from main.
My DLL / SO: loaded library that uses the wxWidgets DLL / SO. It also does not implement a wxApp of any sort. It calls wxInitialize from its DllMain (PROCESS_ATTACH) / __attribute__ ((constructor)) MyDllInit function.
All wxWidgets compile flags are the same for both Windows XP using VS2005 and Ubuntu Feisty using KDevelop.
apps:
__WXGTK__ or __WXMSW___
WXUSINGDLL
DLL / SO:
__WXGTK__ or __WXMSW___
WXUSINGDLL
_USRDLL (Visual Studio only)
wxUSE_GUI=0
wxWidgets DLL / SO built for Linux with --enable-shared --enable-monolithic --with-gtk and for windows from the command line with SHARED=1 MONOLITHIC=1
Both app # 2 and app # 3 run correctly on both OSes. App # 1 fails the same on both OSes - it hits the ASSERT on line 65 on /src/common/init.cpp. I've attached the screen shot from the assertion on windows. I don't understand why it's down into the wxDummyConsoleApp class since this is not a console app. If I remove the wxInitialize from my DLL/ SO, all 3 apps run fine.
App 1:
Code: Select all
.h file
class CMemMgrGuiApp : public wxApp
{
public:
CMemMgrGuiApp ();
virtual bool OnInit ();
virtual int OnExit ();
};
DECLARE_APP (CMemMgrGuiApp)
.cpp file
IMPLEMENT_APP (CMemMgrGuiApp)
bool CMemMgrGuiApp::OnInit ()
{
CMemMgrGuiView *frame;
wxApp::OnInit ();
wxInitAllImageHandlers ();
// create main window
frame = new CMemMgrGuiView (NULL, -1, "MemMgrGui", wxDefaultPosition,
wxDefaultSize, wxDEFAULT_FRAME_STYLE);
// set main window icon
wxIcon icon (glb_MemMgrGui_icon);
frame->SetIcon (icon);
frame->Fit ();
frame->CenterOnScreen ();
frame->Show (TRUE);
SetTopWindow (frame);
return true;
}
Code: Select all
.h file
class CMemMgrDllSo
{
public:
BOOL InitInstance ();
void ExitInstance ();
};
.cpp file
CMemMgrDllSo glb_theDllSo;
#ifdef WIN32
BOOL APIENTRY DllMain (HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
return glb_theDllSo.InitInstance ();
else if (ul_reason_for_call == DLL_PROCESS_DETACH)
glb_theDllSo.ExitInstance ();
return TRUE;
}
#else
void __attribute__ ((constructor)) MyDllInit (void);
void __attribute__ ((destructor)) MyDllExit (void);
#endif
void MyDllInit ()
{
glb_theDllSo.InitInstance ();
}
void MyDllExit ()
{
glb_theDllSo.ExitInstance ();
}
#endif
BOOL CMemMgrDllSo::InitInstance ()
{
if (!wxInitialize ())
{
// can't init wxWidgets - major catastrophe!!
return FALSE;
}
wxLogDebug ("CMemMgrDllSo::InitInstance ...");
}
I figured I'd post my "solution" here since no-one was able to come up with one. The root of the problem is due to the wxInitialize in the DLL getting called before the IMPLEMENT_APP code in the wx GUI. I had to do two things to get this to work and only have one DLL / SO for use by both wx and non-wx GUIs.
Step 1: Force the wx GUI app initialization to occur first.
This means that the wx GUI cannot implicitly load the DLL / SO i.e. it cannot link with the .lib / .la file. Therefore, the wx GUI must use wxDynamicLibrary to load my DLL
Step 2: Do not call wxInitialize in the DLL if called by a wx GUI.
If this step is not done, there are memory leaks from the wx library. In the DLL's initialization routine, I check the return value of wx::GetInstance. If it is NULL, the DLL is called by a non-wx GUI and should call wxInitialize. If the value is not NULL, do not call wxInitialize.
FYI,
Judy
Step 1: Force the wx GUI app initialization to occur first.
This means that the wx GUI cannot implicitly load the DLL / SO i.e. it cannot link with the .lib / .la file. Therefore, the wx GUI must use wxDynamicLibrary to load my DLL
Step 2: Do not call wxInitialize in the DLL if called by a wx GUI.
If this step is not done, there are memory leaks from the wx library. In the DLL's initialization routine, I check the return value of wx::GetInstance. If it is NULL, the DLL is called by a non-wx GUI and should call wxInitialize. If the value is not NULL, do not call wxInitialize.
FYI,
Judy