我从VS2015命令行构建了一个静态版本的Qt,其中包含以下内容:
..\Src\configure -prefix E:\Qt\Qt5.9.1\5.9.1\QtStatic -static -static-runtime -nomake tests -nomake examples -debug-and-release -developer-build -opensource -confirm-license -opengl desktop
我使用Cmake来构建我的主应用程序和一个dll,使用/ MTd选项并链接(在调试模式下)所有" * d.lib" Qt / lib和/ plugins / platforms目录中的文件以及C:/ Program Files(x86)/ Microsoft SDKs / Windows / v7.1A / Lib / x64文件夹。
我的主要职能:
#include "myWindowClass.h"
#include <QApplication.h>
int main(int argc, char **argv) {
QApplication app(argc, argv);
myWindowClass *mwc = new myWindowClass();
mwc->show();
return app.exec();
}
myWindowClass.h(STATIC_BUILD在Cmake中定义):
#pragma once
#include <QMainWindow.h>
#include "ui_mainWindow.h"
#include <QtPlugin>
#include <QLibrary>
#include "myDllClass.h"
#ifdef STATIC_BUILD
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
#endif
typedef MyDllClass* (*MyDll)();
namespace Ui {
class myWindowClass;
}
class myWindowClass : public QMainWindow {
Q_OBJECT
public:
myWindowClass(QWidget *parent = 0);
~myWindowClass() {
delete ui;
}
public slots:
void launchMyDialog();
void loadMyDll();
private:
Ui::MainWindow *ui;
QLibrary *lib;
MyDllClass *myc;
};
myWindowClass.cpp:
#include "myWindowClass.h"
myWindowClass::myWindowClass(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void myWindowClass::launchMyDialog() {
if (lib)
if (lib->isLoaded())
myc->launchDialog();
}
myWindowClass::loadMyDll() {
lib = new QLibrary("MyDLL.dll");
lib->load();
if (lib->isLoaded()) { // Library is found to be loaded
auto create = (MyDll)lib.resolve("Create");
if (create) // Create resolves successfully
myc = create(); // create executes successfully
}
}
我使用Qt Designer构建了一个mainWindow.ui,它具有连接到loadMyDll()和launchMyDialog()函数的按钮。
在myDllClass.h中:
#if defined (WIN32) && defined (BUILD_SHARED_LIBS)
#if defined (_MSC_VER)
#pragma warning(disable: 4251)
#endif
#if defined(MyDLL_EXPORT)
#define MYLIB_EXPORT __declspec(dllexport)
#else
#define MYLIB_EXPORT __declspec(dllimport)
#endif
#else
#define MYLIB_EXPORT
#endif
struct MyDllClass {
virtual void launchDialog() = 0;
};
class MyClass : public MyDllClass
{
public:
MyClass() {}
~MyClass() {}
void launchDialog();
};
在myDllClass.cpp中:
#include "myDllClass.h"
#include "MyDialog.h"
MyClass::launchDialog() {
myDialogClass *pDllDialog = new myDialogClass(); // Runtime error "QWidget: must construct a QApplication before a QWidget"
pDllDialog->raise();
pDllDialog->activateWindow();
pDllDialog->exec();
}
extern "C" MYLIB_EXPORT MyDllClass * Create() {
return new MyClass();
}
在myDialog.h中:
#pragma once
#include <QDialog>
#include "ui_MyDialog.h"
class myDialogClass : public QDialog {
Q_OBJECT
public:
myDialogClass(QWidget *parent = 0) :
QDialog(parent), ui(new Ui::Dialog) {
ui->setupUi(this);
}
~myDialogClass() {
delete ui;
}
private:
Ui::Dialog *ui;
};
同样使用Qt Designer,我只用OK和Cancel按钮构建了一个myDialog.ui。
错误出现在指示的位置。在myDialogClass的构造函数中设置断点表明永远不会到达第一行ui-> setupUi(this);失败发生在此之前。
请注意,使用/ MDd选项构建并使用Qt dll的此代码运行正常。将MyDLL构建为静态库并链接它也可以正常运行(直接调用Create()而不是先解析它)。它只是在使用Qt的静态构建来构建MyDLL作为dll而遇到问题。
这是可以做到的吗?如果是这样,我哪里错了?
我尝试过的东西不起作用或者不构建:包括myDialog.h中的Q_IMPORT_PLUGIN宏;试图在dll中构建一个新的QApplication;在发布/ MT中构建发布库。
我没有尝试过的事情:在主app和MyDLL之间混合使用Qt版本的静态和共享版本;混合Qt的静态和共享版本以及运行时库。我真的不感兴趣:关键是要有一个不依赖于Qt或运行时dll的应用程序。