Init wxApp from Linux daemon

Do you have a typical platform dependent issue you're battling with ? Ask it here. Make sure you mention your platform, compiler, and wxWidgets version.
rudolfninja
Experienced Solver
Experienced Solver
Posts: 86
Joined: Tue Aug 28, 2018 1:02 pm
Location: Belarus

Init wxApp from Linux daemon

Post by rudolfninja » Thu Jun 06, 2019 12:24 pm

Hi
The situation is following:
I've got main thread of Linux daemon (lets say thread A) which has no UI. A thread may create secondary threat (lets call it B threat) in which I need to display border frame. Currently when I'm trying to create the border from B threat my daemon is crashed. I found that I need init wxApp firstly.
In header file of the daemon class I created global variable

Code: Select all

wxApp g_wxApp;
Then in daemon's BeforeMainProc(int argc, char* argv[]) (this func is called from program's main() function) I do (in separate thread):

Code: Select all

std::thread([]{
                /*wxApp::SetInstance(&g_wxApp);
                bool initialized = wxEntryStart(argc, argv);

                if (!initialized)
                {
                    DUMPER_FATAL("Failed to initialize GTK");
                    std::terminate();
                }*/
                wxIMPLEMENT_APP(g_wxApp);
            }).detach();
wxApp is inited in separate thread in order to not block main thread by event loop.
Then inside of class that is used in B thread I call following:

Code: Select all

wxGetApp()->CallAfter(
[this, borderThickness]{m_borderWindow = new LinuxBorderWindow(borderThickness);
m_borderWindow->Show(true);}
)
The problem is when I try to compile this code, I see error that
error: ‘wxGetApp’ was not declared in this scope
So the question is how to init wxApp in the right way in order to show my border from the secondary threat?

Just to summarize: I need to init wxApp in main thread and then using CallAfter method (of the inited wxApp instance) I want to show wxFrame on the screen from another thread.

Thanks.
Last edited by rudolfninja on Thu Jun 06, 2019 2:44 pm, edited 1 time in total.

alys666
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 245
Joined: Tue Oct 18, 2016 2:31 pm

Re: Init wxApp from Linux daemon

Post by alys666 » Thu Jun 06, 2019 1:34 pm

about wxGetApp
https://docs.wxwidgets.org/3.0/group__g ... 92a3a4c6c
This function doesn't exist in wxWidgets but it is created by using the wxIMPLEMENT_APP() macro.
Thus, before using it anywhere but in the same module where this macro is used, you must make it available using wxDECLARE_APP().
ubuntu 16.04, wxWidgets 3.0.4

rudolfninja
Experienced Solver
Experienced Solver
Posts: 86
Joined: Tue Aug 28, 2018 1:02 pm
Location: Belarus

Re: Init wxApp from Linux daemon

Post by rudolfninja » Thu Jun 06, 2019 1:39 pm

Thanks for the reply.
So do you mean I can't call this func from another thread (as follows from another module) or do you mean that firstly I need call wxDECLARE_APP() macro before calling wxGetApp?

alys666
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 245
Joined: Tue Oct 18, 2016 2:31 pm

Re: Init wxApp from Linux daemon

Post by alys666 » Thu Jun 06, 2019 2:18 pm

rudolfninja wrote:
Thu Jun 06, 2019 1:39 pm
Thanks for the reply.
So do you mean I can't call this func from another thread (as follows from another module) or do you mean that firstly I need call wxDECLARE_APP() macro before calling wxGetApp?
compiler says, that this functions has not be declared. He just cannot find it in current scope.
but this this macro declares this function :)
you dont need to "call". you need to declare it - write somewhere after you application class declaration -
wxDECLARE_APP(myAppClass)
ubuntu 16.04, wxWidgets 3.0.4

rudolfninja
Experienced Solver
Experienced Solver
Posts: 86
Joined: Tue Aug 28, 2018 1:02 pm
Location: Belarus

Re: Init wxApp from Linux daemon

Post by rudolfninja » Thu Jun 06, 2019 2:42 pm

I added this macro in the header file of the class I try to create in B thread. Still can't compile.

Code: Select all

In file included from /home/me/dev/rtv/SessionHelper/LinuxSessionHelperModule.h:8:0,
                 from /home/me/dev/rtv/SessionHelper/LinuxSessionHelperModule.cpp:2:
/home/me/dev/rtv/SessionHelper/LinuxSessionHelperModule.cpp: In lambda function:
/home/me/dev/rtv/SessionHelper/LinuxSessionHelperModule.cpp:105:17: error: a function-definition is not allowed here before ‘{’ token
                 wxIMPLEMENT_APP(wxApp);
                 ^
/home/me/dev/rtv/SessionHelper/LinuxSessionHelperModule.cpp:105:17: error: a function-definition is not allowed here before ‘{’ token
                 wxIMPLEMENT_APP(wxApp);
                 ^
/home/me/dev/rtv/SessionHelper/LinuxSessionHelperModule.cpp:105:17: error: a function-definition is not allowed here before ‘{’ token
                 wxIMPLEMENT_APP(wxApp);

alys666
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 245
Joined: Tue Oct 18, 2016 2:31 pm

Re: Init wxApp from Linux daemon

Post by alys666 » Thu Jun 06, 2019 2:47 pm

rudolfninja wrote:
Thu Jun 06, 2019 2:42 pm
I added this macro in the header file of the class I try to create in B thread. Still can't compile.
header in c/c++ is just a piece of text, physically included in other texts, where preprocessor meets #include directive. it's not Pascal with definition units.
make this once in source file where your app class is implemented(where you write bodies of his functions)
ubuntu 16.04, wxWidgets 3.0.4

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3469
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Init wxApp from Linux daemon

Post by ONEEYEMAN » Thu Jun 06, 2019 2:50 pm

Hi,
The error is pretty self-explanatory I think.
Take this macro call

Code: Select all

wxIMPLEMENT_APP()
out of lambda's.

Thank you.

alys666
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 245
Joined: Tue Oct 18, 2016 2:31 pm

Re: Init wxApp from Linux daemon

Post by alys666 » Thu Jun 06, 2019 2:54 pm

ONEEYEMAN wrote:
Thu Jun 06, 2019 2:50 pm
Hi,
The error is pretty self-explanatory I think.
Take this macro call

Code: Select all

wxIMPLEMENT_APP()
out of lambda's.
Thank you.
aaaaaah.. i don't accurately look to first post... declaration is inside lambda???
or it's already outside lambda, but in header... both variants are errors of course.
ubuntu 16.04, wxWidgets 3.0.4

rudolfninja
Experienced Solver
Experienced Solver
Posts: 86
Joined: Tue Aug 28, 2018 1:02 pm
Location: Belarus

Re: Init wxApp from Linux daemon

Post by rudolfninja » Thu Jun 06, 2019 3:04 pm

I removed this macro from lambda, still have the error.
The problem is that, class which I use in threat B (and from which I call wxGetApp) is in different module than main class, so if I use wxDECLARE_APP(wxApp); macro inside of module with main class it is still impossible to use wxGetApp function from the module with class B.

Just to summarize: I need to init wxApp in main thread and then using CallAfter method (of the inited wxApp instance) I want to show wxFrame on the screen from another thread.

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3469
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Init wxApp from Linux daemon

Post by ONEEYEMAN » Thu Jun 06, 2019 3:11 pm

Hi,
Bottom line - you can't do that. None of wx GUI classes are thread safe.

Accessing/creating GUI shuold be done in the same thread that creates wxWidgets wxApp object.

So, even if the code compiles it will not work as you intend it to.

Please re-think your design.

Thank you.

alys666
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 245
Joined: Tue Oct 18, 2016 2:31 pm

Re: Init wxApp from Linux daemon

Post by alys666 » Thu Jun 06, 2019 3:13 pm

to be successfully crashed, a program must be successifuly compiled.
are you still at first stage?
i never tried to run wx application from different thread, but it could be possible. then thread B will drive all wxWidgets functionality, and at least wxDECLARE_APP must be in his code among his definitions, as i understand things.
ubuntu 16.04, wxWidgets 3.0.4

alys666
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 245
Joined: Tue Oct 18, 2016 2:31 pm

Re: Init wxApp from Linux daemon

Post by alys666 » Thu Jun 06, 2019 3:18 pm

ONEEYEMAN wrote:
Thu Jun 06, 2019 3:11 pm
Hi,
Bottom line - you can't do that. None of wx GUI classes are thread safe.
Accessing/creating GUI shuold be done in the same thread that creates wxWidgets wxApp object.
So, even if the code compiles it will not work as you intend it to.
Please re-think your design.
Thank you.
as i read wxWidgets could be run from secondary thread(do not read it in details) - so some secondary thread could drive wxWIdgets, but then the main app thread must not touch wxWIdgets objects without care about thread safety.
Imo his design could work. bit not sure he could implement it properly without heap of mistakes
ubuntu 16.04, wxWidgets 3.0.4

User avatar
doublemax
Moderator
Moderator
Posts: 14098
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Init wxApp from Linux daemon

Post by doublemax » Thu Jun 06, 2019 4:09 pm

I know very little about Linux daemons, but i'm surprised they could use a GUI at all.

Regardless of that, maybe you should look into the option to have a gui-less daemon which communicates with an additional gui app using IPC.
Use the source, Luke!

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3469
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Init wxApp from Linux daemon

Post by ONEEYEMAN » Thu Jun 06, 2019 5:01 pm

Hi,
alys666 wrote:
Thu Jun 06, 2019 3:18 pm
ONEEYEMAN wrote:
Thu Jun 06, 2019 3:11 pm
Hi,
Bottom line - you can't do that. None of wx GUI classes are thread safe.
Accessing/creating GUI shuold be done in the same thread that creates wxWidgets wxApp object.
So, even if the code compiles it will not work as you intend it to.
Please re-think your design.
Thank you.
as i read wxWidgets could be run from secondary thread(do not read it in details) - so some secondary thread could drive wxWIdgets, but then the main app thread must not touch wxWIdgets objects without care about thread safety.
Imo his design could work. bit not sure he could implement it properly without heap of mistakes
You misread my reply.
If you want to do MT programming, the GUI must be created and accessed in the same thread where you created wxApp object, because the thread which creates wxApp object is considered primary thread.
If you create wxApp-derived object in one thread, than everything GUI-related should be created/accessed on the same thread.

Therefore his design will not work.

Thank you.

alys666
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 245
Joined: Tue Oct 18, 2016 2:31 pm

Re: Init wxApp from Linux daemon

Post by alys666 » Thu Jun 06, 2019 5:47 pm

ONEEYEMAN wrote:
Thu Jun 06, 2019 5:01 pm
You misread my reply.
If you want to do MT programming, the GUI must be created and accessed in the same thread where you created wxApp object, because the thread which creates wxApp object is considered primary thread.
If you create wxApp-derived object in one thread, than everything GUI-related should be created/accessed on the same thread.

Therefore his design will not work.

Thank you.
macro just declares a global function wxGetApp:

Code: Select all

#define wxDECLARE_APP(appname)    extern appname& wxGetApp()

so can be declared anywhere
more interesting is macro

Code: Select all

// Use this macro if you want to define your own main() or WinMain() function
// and call wxEntry() from there.
#define wxIMPLEMENT_APP_NO_MAIN(appname)                                    \
    appname& wxGetApp() { return *static_cast<appname*>(wxApp::GetInstance()); }    \
    wxAppConsole *wxCreateApp()                                             \
    {                                                                       \
        wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE,         \
                                        "your program");                    \
        return new appname;                                                 \
    }                                                                       \
    wxAppInitializer                                                        \
        wxTheAppInitializer((wxAppInitializerFunction) wxCreateApp)

so it look like you could start wxWIdgets app from secondary thread, and of course use wxWidgets from this thread, not from main thread given to you at start. it's for first look, of course.
ubuntu 16.04, wxWidgets 3.0.4

Post Reply