Problem with wxMSW and setting the module instance handle.

Jurko Gospodnetić jurko_for_boost at mail.inet.hr
Sun May 20 15:21:51 PDT 2007


   Hi Vadim.

> JG>    Just wanted to report that there is a bit problematic detail with
> JG> wxMSW application startup design. There wxEntry() sets the Windows
> JG> module instance handle using the internal wxWidgets wxSetInstance() API
> JG> found in the msw/private.h header.
> 
>  This is indeed a problem but it's not clear what to do about it. We can,
> of course, define an alternative wxEntryStart() taking HINSTANCE but how
> useful will it be? And other than that where are we supposed to get the
> HINSTANCE from?
> 
>  For an EXE it's easy enough: we can use GetModuleHandle(NULL). But if wx
> is a static library linked into a DLL, this would return a wrong handle.
> And I don't really know how to get the right one. Apparently Microsoft
> linker provides __ImageBase pseudo variable which contains HINSTANCE but
> this is for MSVC only. There is also GetModuleHandleEx() but it only works
> on XP and later. So there is nothing which works in all cases other than
> using the parameter to WinMain.
> 
>  So, again, while we should probably add wxEntryStart() with the same
> signature as WinMain() anyhow, I don't see any good way of solving this
> problem.

   I have been thinking about the problem a bit so here are my thoughts 
on the subject. Note though that most API names above have been 
constructed on-demand and I am not sure if they would be acceptable or 
would have to be renamed. Also... not all details have been ironed out :-).

   If you add a new wxEntryStart() for each new application startup type 
(e.g. with and without HINSTANCE) then each wxEntryStart() needs to be 
wrapped with a separate wxEntry() function. This would also obviously be 
platform specific.

   Another idea that could possibly lead to a cleaner solution is to 
drop the current 'wxApp class derivable for specific applications' 
approach and have applications initialize/run/finalize wxWidgets by 
calling wxInitialize()/wxRun()/wxFinalize(). Then wxApp may be freely 
derived from internally for each platform (wxAppMSW/wxAppGTK/...).

   Then, for instance, wxAppMSW could contain as many platform specific 
constructors or initializers (e.g. setInstance(), setArgcArgv(), 
setCommandLine(), etc.) as needed and platform specific 
initialization/finalization code could be wrapped inside virtual (and 
private) member functions initialize()/finalize() taking no parameters. 
Such functions would then adapt to whichever startup parameters got set 
in their application object.

   Customized application startup/shutdown code could access the 
wxWidgets platform specific application object using some wxGetApp() 
function similar to how this is done now.

   Platform independent wxInitialize()/wxFinalize() would call the 
platform dependent wxApp::initialize()/finalize() virtual functions plus 
trigger what ever other platform-independent magic they need. wxRun() 
would simply call wxApp::OnRun(). (These functions could possibly be 
implemented as wxApp member functions instead of stand-alone ones.)

   Simple use-cases such as most wxWidgets demos and applications not 
requiring customized wxWidgets startup/shutdown could be implemented 
similar to how they have been implemented so far - using an 
IMPLEMENT_APP() macro which would either create an object derived from 
some ApplicationBase class (used only to call a virtual application 
defined initialization member function after initializing wxWidgets) or 
simply take an initialization function parameter. It would then prepare 
a WinMain()/main()/... startup function triggering tasks similar to what 
wxEntry() does now:
   1. Create the platform specific wxApp object and set its startup 
parameters.
   2. wxInitialize().
   3. Call the application specific initialization function (not needed 
in case of customized startup/shutdown code as then the custom code 
already knows when wxInitialize() terminates).
   4. wxRun().
   5. wxFinalize().

   On MSW this leaves a question of SEH handling which I think should be 
handled similar to how it is handled now - using a documented API/macro 
system for wrapping application code in a SEH exception safety wrapper. 
In simple cases wxWidgets defined startup function would implement this 
wrapper automatically and any customized applications would need to 
decide for themselves whether they need it.

   Some pluses for this design are:
   * Works the same even for (imaginary) platforms using strings to 
identify application instances or other such platform dependent data.
   * Platform dependent wxWidgets application objects hold platform 
specific data instead of having it stored in separate global objects as 
it is now.
   * No more 'undocumented hacks' such as wxSetInstance() on MSW, not 
intuitive from standard code (so much that even demo applications have 
errors related to using them). Each application needing customized 
wxWidgets initialization on a specific platform simply needs to check 
the platform specific wxApp derived class documentation and related 
startup settings can be checked in that class's initialize() function so 
any startup configuration mistakes may be detected as soon as possible.
   * 'Standard' wxWidgets applications, not needing any startup/shutdown 
customization, could be written as they have been. If they need their 
own application object - they may provide it independent of the 
wxWidgets application class.

   I would like to hear other's thoughts on this.

   Best regards,
     Jurko Gospodnetić





More information about the wx-dev mailing list