Page 1 of 1

dll for both wx and non-wx GUIs (no longer debug v optimized

Posted: Fri Sep 14, 2007 6:35 pm
by JudyL
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

Posted: Tue Sep 18, 2007 2:36 am
by davebee
Have you tried using in your project/make file the following marcos?

"_USRDLL"
"DLL_EXPORTS"
wxUSE_GUI=0
"WXUSINGDLL"

Good luck! :)
Dave

Posted: Tue Sep 18, 2007 12:08 pm
by JudyL
I've got some, but not all of those options. I'll give it a try as soon as I finish the feature I'm working on now.

Thanks,
Judy

Posted: Tue Sep 18, 2007 2:36 pm
by JudyL
WXUSINGDLL was the key. Upon rechecking, I had it defined in my windows build files but not in all of my Linux ones.

DOH!! :oops:

Thanks Dave

Posted: Tue Sep 18, 2007 4:28 pm
by JudyL
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:

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;
}
DLL / SO:

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 ...");
}


Posted: Tue Sep 18, 2007 4:37 pm
by JudyL
Forget this in my long-winded missive

The problem is no longer dependent on debug v release optimized) mode. In release mode, it just doesn't execute. In debug mode, I get the stack trace / assert info.

Posted: Fri Sep 28, 2007 1:30 pm
by JudyL
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