Динамически загружается QTGui

Я пишу приложение QT, и я хотел, чтобы скомпилированный двоичный файл был совместим со средами GUI и CLI (установлены без X11).

Вот моя основная функция, которая использует QApplication или QCoreApplication:

int main(int argc, char *argv[]){
// SOME COMMON CODE will be executed before this
bool myGUI = getenv("DISPLAY") != 0;

if(myGUI){
QApplication a(argc, argv);
client w; // A MainWindow Object
w.show();
doStuff();
return a.exec();
}else{
QCoreApplication a(argc, argv);
doStuff();
return a.exec();
}

return 1;

}

Теперь QT создает двоичный файл, имеющий libQtGui в качестве динамически разделяемого объекта. Я хотел знать, можно ли динамически загружать libQtGui, чтобы он мог работать в средах CLI без необходимости устанавливать все библиотеки, необходимые для libQtGui.

2

Решение

Это не практично, пытаться это сделать. Теоретически это возможно, но для огромного количества вещей вам нужно будет создать C-оболочки.

Вместо этого вы можете попробовать разделить часть GUI вашего приложения на собственную разделяемую библиотеку и выполнить dlopen (). Например, gui.cpp:

// Needs to be extern "C" so that dlopen() can find it later.
extern "C"int runGui(int argc, char *argv[])
{
QApplication a(argc, argv);
client w;
w.show();
doStuff();
return a.exec();
}

Вы компилируете вышеизложенное как общую библиотеку, ссылаясь на QtGui. Например:

g ++ -c -fPIC $ (pkg-config QtGui --cflags) -o gui.o gui.cpp
g ++ -shared -o gui.so gui.o $ (pkg-config QtGui --libs)

Это даст вам gui.so, который вы можете затем dlopen () в вашей основной программе:

#include <dlfcn.h>

int main(int argc, char *argv[])
{
// SOME COMMON CODE will be executed before this
bool myGUI = getenv("DISPLAY") != 0;
int ret = 0;

if (myGUI) {
void* handle = dlopen("./gui.so", RTLD_NOW);
if (!handle) {
// Error: dlopen failed
}
dlerror(); // Clear/reset errors.

// Create a function pointer type for runGui()
typedef int (*runGui_t)(int, char**);

// Load the address of runGui() and store it in a
// function pointer. The function pointer name doesn't
// have to be the same as the function we're loading.
runGui_t runGui = (runGui_t)dlsym(handle, "runGui");

const char* dlsym_error = dlerror();
if (dlsym_error) {
// Error: dlsym failed.
// 'dlsym_error' contains the error msg.
}

// Call the function as usual by using our 'runGui' pointer.
ret = runGui(argc, argv);
dlclose(handle);
} else {
QCoreApplication a(argc, argv);
doStuff();
ret = a.exec();
}
return ret;
}

Обратите внимание, что при сборке вышеупомянутого main.cpp вы не должны ссылаться на QtGui, чтобы он работал в системах, где libQtGui.so недоступен. В этом случае dlopen () не сможет загрузить gui.so. В этот момент вы можете вернуться к коду без графического интерфейса (я не делал этого в приведенном выше примере.)

3

Другие решения

Это не вопрос о Qt, это вопрос о c ++

Вы можете найти ответ здесь
Динамически загружать функцию из DLL

Но в основном я думаю, что это плохая идея, если вы хотите использовать чистое консольное приложение или смешанное консольное / графическое приложение, вы должны разрешить его во время компиляции с помощью #ifdef.

#ifdef WITH_GUI
if(myGUI){
QApplication a(argc, argv);
client w; // A MainWindow Object
w.show();
doStuff();
return a.exec();
}else{
#endif
QCoreApplication a(argc, argv);
doStuff();
return a.exec();
#ifdef WITH_GUI
}
#endif

И добавьте некоторые аргументы запуска. Например ./myapp —start-gui для версии, скомпилированной с поддержкой графического интерфейса.

0

По вопросам рекламы [email protected]