Я пишу приложение 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.
Это не практично, пытаться это сделать. Теоретически это возможно, но для огромного количества вещей вам нужно будет создать 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. В этот момент вы можете вернуться к коду без графического интерфейса (я не делал этого в приведенном выше примере.)
Это не вопрос о 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 для версии, скомпилированной с поддержкой графического интерфейса.