PDA

View Full Version : 1 instance of QApplication in my application that uses static libraries



hml
2nd January 2010, 17:16
Hello,
the problem is "QWidget: Must construct a QApplication before a QPaintDevice".
Please read below

on win32/vs2008 and linux32/g++4.4,
I build static libraries and an executable/binary that links against those static libraries.

I have a "plot" static library( plot.lib or libplot.a ) that includes a main.cpp translation unit.
This defines a namespace-scope variable


namespace NS1 { namespace NS2 {
int argc_for_qapp=0;
QApplication app(argc_for_qapp, 0);
}
}

so the symbol NS1::NS2::app is the variable.

in another translation unit in "plot", there is


namespace NS1 { namespace NS2 {
extern QApplication app;

void f()
{
...
app.exec();
}

}}


There is the application's main.cpp that calls the function f().

As I understand there is no guarantee of the initialization of globals between translation units, but there is a guarantee that all of them are initialized before the main function.

In Debug there is no problem, in Release there is the problem:
"QWidget: Must construct a QApplication before a QPaintDevice"

In Release vs2008, I made sure the linker options for the executable that includes, in Linker/Optimization/References => "Keep Unreferenced Data"
Linker/Optimization/Enable COMDAT Folding => "Do Not Remove Redundant COMDATs "

so the reference to NS1::NS2::app that is in another translation unit is not removed.

Again in debug mode, this works fine.
in release/linux32/g++4.4, same error.

rds,

faldzip
2nd January 2010, 17:36
I don't really understand why you create global QApplication object in your library.
Can't you do it in normal way, so it is created in main() function in the executable:


int main(int argc, char **argv)
{
QApplication a(argc, argv);
// ... some code calling you library functions where widgets are created ...
return a.exec();
}

?
And if you want additional event loop then use QEventLoop in you lib.
This my main.cpp works unless you want to create a global widget object, which you shouldn't. If you really want you have to create global pointer to QWidget and set it pointing to a widget created on a heap. What's more, it is highly recommended to make all widgets on heap (look into Qt docs).

hml
2nd January 2010, 18:23
Thanks.
Only part of my application uses Qt. It is able to run only in text mode without any graphics.
I want to keep all Qt related aspects inside 1 static library.
I may alo use write another static library that provides the same interface but using another toolkit.

I will use then a namespace-scope QApplication* instead and will initialize it on 1st time of use explicitly.

thanks,

wysota
2nd January 2010, 19:19
You should hide everything in the library implementation. You should provide an abstract class that can be implemented in a number of different ways. One of them can be to use QApplication and the implementation would be responsible for creating the instance of it and calling exec on it, although remember that by doing so you agree to specific semantics - exec() blocks linear code execution and makes your application event-driven.

As for the error, you probably have a global or static paint device (widget, image?) somewhere. Using the "extern" modifier is probably also wrong, especially that QApplication is a singleton you can call through its instance().