wxWidgets GUI from within DLL

1,308 views
Skip to first unread message

damateem

unread,
Feb 21, 2012, 8:20:47 PM2/21/12
to wx-users
My setup is wxWidgets 2.8.11, Win7 Pro 64, MinGW32.


I'm trying to use wxWidgets GUI elements from within a DLL. I'm using
the dll sample from wxWidgets 2.9 as a starting point. That sample is
not 100% compatible with 2.8.11, so I've had to make a few modifications
that basically amount to multiple calls for things that now have
wrappers in 2.9.

I think I've converted it all correctly. It builds fine, but when I run
it, I get an error window stating the following.

"Can't create window of class wxWindowClassNR (error 1407: cannot find
window class.)"

and in DebugView, I get messages such as

"[5824] 19:18:57: In file ../../src/msw/app.cpp at line 364:
'RegisterClass(frame)' failed with error 0x00000582 (class already
exists.)."

So I get the feeling there is a conflict with window class names, as
described here: http://trac.wxwidgets.org/ticket/9031. If you read that
link all the way to the bottom, you'll discover that the issue described
resulted from using the same HMODULE twice, in the App and in the DLL.
However, I believe I am acquiring the HMODULE correctly. Here is the
code I'm using.

HMODULE hmod;
GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(char *)&gs_wxMainThread, &hmod );
const HINSTANCE hInstance =hmod;

Any ideas what I'm doing wrong?

Has anyone gotten the 2.9 dll sample to work under 2.8.x?

Thanks,
David

Igor Korot

unread,
Feb 21, 2012, 9:57:53 PM2/21/12
to wx-u...@googlegroups.com
Hi,

To make you life easier:

1. Get wx-2.9 sources from SVN.
2. Copy the samples/dll folder from 2.9 to 2.8.
3. Get the Makefile from any sample folder in 2.8 and copy it to
2.8/samples/dll.
4. Modify copied Makefile so that it will correctly picks up everything.
5. Try building the sample and execute it.

Thank you.

>
> Thanks,
> David
>
> --
> Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.
>
> To unsubscribe, send email to wx-users+u...@googlegroups.com
> or visit http://groups.google.com/group/wx-users

Vadim Zeitlin

unread,
Feb 22, 2012, 8:21:54 AM2/22/12
to wx-u...@googlegroups.com
On Tue, 21 Feb 2012 20:20:47 -0500 damateem <dama...@gmail.com> wrote:

d> and in DebugView, I get messages such as
d>
d> "[5824] 19:18:57: In file ../../src/msw/app.cpp at line 364:
d> 'RegisterClass(frame)' failed with error 0x00000582 (class already
d> exists.)."
d>
d> So I get the feeling there is a conflict with window class names, as
d> described here: http://trac.wxwidgets.org/ticket/9031.

Yes.

d> However, I believe I am acquiring the HMODULE correctly. Here is the
d> code I'm using.
d>
d> HMODULE hmod;
d> GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
d> GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
d> (char *)&gs_wxMainThread, &hmod );
d> const HINSTANCE hInstance =hmod;
d>
d> Any ideas what I'm doing wrong?

Where do you call wxSetInstance()?

Regards,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/

damateem

unread,
Feb 22, 2012, 9:28:08 AM2/22/12
to wx-u...@googlegroups.com
> d> Any ideas what I'm doing wrong?
>
> Where do you call wxSetInstance()?
>

I'm not calling wxSetInstance(). It's never called in the dll sample.

Does 2.9 call it automatically?

The dll sample passes hInstance to wxEntry.

// Run the app:
wxEntry(hInstance);

Is that not enough in 2.8?

Thanks,
David

Vadim Zeitlin

unread,
Feb 22, 2012, 10:22:27 AM2/22/12
to wx-u...@googlegroups.com
On Wed, 22 Feb 2012 09:28:08 -0500 damateem <dama...@gmail.com> wrote:

d> > d> Any ideas what I'm doing wrong?
d> >
d> > Where do you call wxSetInstance()?
d>
d> I'm not calling wxSetInstance(). It's never called in the dll sample.
d>
d> Does 2.9 call it automatically?

Yes, it does it from wxEntry(HINSTANCE) overload, sorry for forgetting
about it.

d> Is that not enough in 2.8?

AFAIR it should be enough, wxEntry(HINSTANCE) also does it there. But I'm
almost sure that this doesn't happen in your case (you can add wxLogDebug()
calls printing out the value used to be sure or just check it under
debugger). Would it be possible that you call a wrong wxEntry overload
somehow?

damateem

unread,
Feb 22, 2012, 12:22:12 PM2/22/12
to wx-u...@googlegroups.com
>> Yes, it does it from wxEntry(HINSTANCE) overload, sorry for forgetting
>> about it.

No problem. I took a peek at the 2.8.11 code and found the same thing.

I was able to locate the issue. The dll sample does the following

// We do this before wxEntry() explicitly, even though wxEntry() would
// do it too, so that we know when wx is initialized and can signal
// run_wx_gui_from_dll() about it *before* starting the event loop.
wxInitializer wxInit;
if ( !wxInit.IsOk() )
return 0; // failed to init wx

before calling wxEntry. If I remove these lines, all works as expected.
It appears wxInitializer is registering window classes. If the dll
sample works with 2.9, it must mean that wxInitializer is different
between 2.8.11 and 2.9.

To keep this test, I could call wxSetInstance before creating the
wxInitializer object. Can you think of any problems this might create?

A a few additional notes that could help others trying to get this
sample working under 2.8.11.

1.) wxDISABLE_DEBUG_SUPPORT does not exist in 2.8.11. I moved the
associated code from 2.9 into my application.
2.) MSWGetModuleHandle does not exist in 2.8.11. I replaced it with
GetModuleHandleExA.
3.) You can't use DllMain to create/destroy the DLL's wxApp thread
because only one thread in a process can run when in DllMain (see
CreateThread on MSDN).

I want the DLL's wxApp thread to start when the DLL is loaded. I don't
want to have to make separate start/stop function calls. Can you think
of a way to make this happen?

Thanks,
David

Vadim Zeitlin

unread,
Feb 22, 2012, 6:04:36 PM2/22/12
to wx-u...@googlegroups.com
On Wed, 22 Feb 2012 12:22:12 -0500 damateem <dama...@gmail.com> wrote:

d> >> Yes, it does it from wxEntry(HINSTANCE) overload, sorry for forgetting
d> >> about it.
d>
d> No problem. I took a peek at the 2.8.11 code and found the same thing.
d>
d> I was able to locate the issue. The dll sample does the following
d>
d> // We do this before wxEntry() explicitly, even though wxEntry() would
d> // do it too, so that we know when wx is initialized and can signal
d> // run_wx_gui_from_dll() about it before starting the event loop.
d> wxInitializer wxInit;
d> if ( !wxInit.IsOk() )
d> return 0; // failed to init wx
d>
d> before calling wxEntry. If I remove these lines, all works as expected.
d> It appears wxInitializer is registering window classes. If the dll
d> sample works with 2.9, it must mean that wxInitializer is different
d> between 2.8.11 and 2.9.

Maybe it was... Looking at the dll sample again I realize that it's more
complicated than I thought. It would be definitely better to just use
wxInitializer instead of doing all the stuff it does if it requires
modifying wxMSW.

d> To keep this test, I could call wxSetInstance before creating the
d> wxInitializer object. Can you think of any problems this might create?

No, setting the instance correctly earlier can't do anything wrong.

d> A a few additional notes that could help others trying to get this
d> sample working under 2.8.11.
d>
d> 1.) wxDISABLE_DEBUG_SUPPORT does not exist in 2.8.11. I moved the
d> associated code from 2.9 into my application.

Instead just drop wxDISABLE_DEBUG_SUPPORT. It is unneeded in 2.8.

d> 2.) MSWGetModuleHandle does not exist in 2.8.11. I replaced it with
d> GetModuleHandleExA.

That's fine.

d> 3.) You can't use DllMain to create/destroy the DLL's wxApp thread
d> because only one thread in a process can run when in DllMain (see
d> CreateThread on MSDN).
d>
d> I want the DLL's wxApp thread to start when the DLL is loaded. I don't
d> want to have to make separate start/stop function calls. Can you think
d> of a way to make this happen?

This is very atypical. Usually some DLL initialization function is called,
why not do it from there?

damateem

unread,
Feb 27, 2012, 11:52:18 PM2/27/12
to wx-u...@googlegroups.com
What does wxInitializer do? Where can I find an example of its use?


d> I want the DLL's wxApp thread to start when the DLL is loaded. I don't
d> want to have to make separate start/stop function calls. Can you think
d> of a way to make this happen?

This is very atypical. Usually some DLL initialization function is called,

Then what is the point of DllMain?

Igor Korot

unread,
Feb 28, 2012, 12:48:35 AM2/28/12
to wx-u...@googlegroups.com
Hi,

2.9 does have a dll sample.

Thank you.

Vadim Zeitlin

unread,
Feb 28, 2012, 9:26:56 AM2/28/12
to wx-u...@googlegroups.com
On Mon, 27 Feb 2012 23:52:18 -0500 damateem <dama...@gmail.com> wrote:

d> What does wxInitializer do? Where can I find an example of its use?

wxInitializer calls wxInitialize() in its ctor and wxUninitialize() in its
dtor.

d> > d> I want the DLL's wxApp thread to start when the DLL is loaded. I don't
d> > d> want to have to make separate start/stop function calls. Can you think
d> > d> of a way to make this happen?
d> >
d> > This is very atypical. Usually some DLL initialization function is called,
d>
d> Then what is the point of DllMain?

Perform some global initialization.

damateem

unread,
Feb 28, 2012, 9:59:29 AM2/28/12
to wx-u...@googlegroups.com
>> wxInitializer calls wxInitialize() in its ctor and wxUninitialize() in its
>> dtor.


I don't see wxInitializer in 2.8.11, but I tried doing the same
wxInitialize and wxUnitialize in my dll without success. Is it possible
to use wxWidgets inside a dll by only calling wxInitialize and
wxUninitialize?

The only success I've had is to create a separate thread as is done in
the dll sample. The dll sample method also does the best job of
decoupling the dll from the application.

Vadim Zeitlin

unread,
Feb 28, 2012, 12:01:29 PM2/28/12
to wx-u...@googlegroups.com
On Tue, 28 Feb 2012 09:59:29 -0500 damateem <dama...@gmail.com> wrote:

d> I don't see wxInitializer in 2.8.11,

It is there nevertheless.

d> but I tried doing the same wxInitialize and wxUnitialize in my dll
d> without success. Is it possible to use wxWidgets inside a dll by only
d> calling wxInitialize and wxUninitialize?

If you don't use wxEntry, you won't have any event loop running so you
won't be able to show any non-modal windows.

d> The only success I've had is to create a separate thread as is done in
d> the dll sample. The dll sample method also does the best job of
d> decoupling the dll from the application.

Yes, this is its purpose. So what's wrong exactly with just doing the same
thing?

damateem

unread,
Feb 29, 2012, 9:23:06 AM2/29/12
to wx-u...@googlegroups.com
>> d> The only success I've had is to create a separate thread as is done in
>> d> the dll sample. The dll sample method also does the best job of
>> d> decoupling the dll from the application.
>>
>> Yes, this is its purpose. So what's wrong exactly with just doing the same
>> thing?

There's no problem with following the dll sample. I've got it working
and I'm very happy with it.

The reason for the wxInitializer questions is that, if I understood your
comments correctly, using wxInitializer would be easier than following
the dll sample. Is that what you meant? Can wxInitializer be used as an
alternative to the dll sample method?

Thanks,
David

Vadim Zeitlin

unread,
Feb 29, 2012, 9:26:37 AM2/29/12
to wx-u...@googlegroups.com
On Wed, 29 Feb 2012 09:23:06 -0500 damateem <dama...@gmail.com> wrote:

d> The reason for the wxInitializer questions is that, if I understood your
d> comments correctly, using wxInitializer would be easier than following
d> the dll sample. Is that what you meant? Can wxInitializer be used as an
d> alternative to the dll sample method?

Err, no. wxInitializer is part of the dll sample method, it's used there.
But the dll sample also shows how to run the event loop in a separate
thread which is needed if you want to show any non modal windows from your
DLL (if you don't need this, then you could indeed omit all the complicated
stuff done by the dll sample and just use wxInitializer).

Regards,

damateem

unread,
Feb 29, 2012, 9:41:14 AM2/29/12
to wx-u...@googlegroups.com

On 2/29/2012 9:26 AM, Vadim Zeitlin wrote:
> On Wed, 29 Feb 2012 09:23:06 -0500 damateem <dama...@gmail.com> wrote:
>
> d> The reason for the wxInitializer questions is that, if I understood your
> d> comments correctly, using wxInitializer would be easier than following
> d> the dll sample. Is that what you meant? Can wxInitializer be used as an
> d> alternative to the dll sample method?
>
> Err, no. wxInitializer is part of the dll sample method, it's used there.
> But the dll sample also shows how to run the event loop in a separate
> thread which is needed if you want to show any non modal windows from your
> DLL (if you don't need this, then you could indeed omit all the complicated
> stuff done by the dll sample and just use wxInitializer).
>
> Regards,
> VZ
>

OK. Now I understand what you meant.

Before implementing the thread, I did try using wxInitialize and
wxUninitialize, but couldn't get wxMessageBox to work that way. Perhaps
I had some other problem.

At this point, I have a working solution so I am moving forward. If I
get time in the future, I will revisit the issue.

Thanks for the help!

David

Reply all
Reply to author
Forward
0 new messages