在 Qt 中使用信号会破坏 DLL

Posted

技术标签:

【中文标题】在 Qt 中使用信号会破坏 DLL【英文标题】:Using signals in Qt breaks DLL 【发布时间】:2016-02-28 14:07:42 【问题描述】:

我正在 Visual Studio 2013 中运行一个模拟程序,我想要一个简单的 GUI 来输出/输入数据。

由于我了解一些 Qt,我决定在 Qt Creator 中编写一个小型 Qt5 程序,将其构建为 .dll 并将此 .dll 链接到我的程序中。然后程序调用一个初始化函数来启动 GUI。

总的来说,这工作得很好。 GUI 就像独立的 Qt 程序一样工作。但是,一旦我像这样向我的 Qt .dll 添加了自定义信号:

//File.h
class MainGui : public QMainWindow

    Q_OBJECT

public:

    explicit MainGui(QWidget *parent = 0);
    ~MainGui();

signals:
    void addItemSignal(QGraphicsView* it);

private slots:
    void addItemImpl(QGraphicsView* it);

private:
    Ui::MainGui *ui;
;

//File.cpp
void MainGui::addItemImpl(QGraphicsView *it)

    //do anything


MainGui::MainGui(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainGui)

    QObject::connect(this, &MainGui::addItemSignal,
                     this, &MainGui::addItemImpl);


MainGui::~MainGui()

    delete ui;

我在尝试启动主程序时收到以下错误消息:

The procedure entry point  could not be located in the dynamic link library e:\...\...\MyQtLibrary.dll.

“point”和“could”之间的两个空格并没有错 - 出于某种原因,入口点似乎根本没有设置任何东西。

经过一些测试,我发现问题在于在信号中使用 Qt 类。以下工作正常:

//File.h
class MainGui : public QMainWindow

    Q_OBJECT

public:

    explicit MainGui(QWidget *parent = 0);
    ~MainGui();

signals:
    void addItemSignal(void* it);

private slots:
    void addItemImpl(void* it);

private:
    Ui::MainGui *ui;
;

//File.cpp
void MainGui::addItemImpl(void*it)

    //do anything


MainGui::MainGui(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainGui)

    QObject::connect(this, &MainGui::addItemSignal,
                     this, &MainGui::addItemImpl);


MainGui::~MainGui()

    delete ui;

这不仅会影响自定义信号,还会影响内置信号:

QObject::connect(models, &QStandardItemModel::dataChanged,[this](a b, x y)
        //do something
    );

这也会破坏 .dll。

我还注意到我必须在 Qt Creator 中完全重建 .dll 才能解决问题。删除任何有问题的信号并仅仅构建并不能解决问题。

仅当 Qt .dll 在 Debug 配置中构建时才会发生该错误。发布配置运行良好。 MSVC 程序是 Debug 还是 Release 似乎都没有效果。我没有更改任何这些配置的任何默认设置(除了一些绝对与它无关的东西)。

我在 Qt Creator 中发现这两种配置的唯一区别是 qmake 的调用:

qmake.exe "D:\Dev\Qt Workspace\ArduGui\ArduGui.pro" -r -spec win32-msvc2013 "CONFIG+=debug" "CONFIG+=qml_debug"

这是对调试配置的调用。在 Release 中,缺少两个调试配置标志。但是当我弄乱 qmake 参数时,结果并没有改变。无论CONFIG+=debugCONFIG+=qml_debug 是否存在,调试配置总是会导致入口点错误。同样,即使添加了两个标志,Release 也始终有效。

所以在这一点上,我正在靠墙奔跑。有没有人有这方面的经验或者可以就如何调试问题提出建议?

更多信息:

我正在使用 Windows 10、MSVC 2013 和 Qt Creator 3.6 和 Qt 5.5.1。 .exe 和 .dll 都是通过各自的 IDE 使用 MSVC++ 12.0 编译器编译的。

【问题讨论】:

【参考方案1】:

如果它适用于void*,但不适用于作为参数传递的 QT 类指针,我猜你还没有注册该类以便能够在信号/插槽机制中使用它:

qRegisterMetaType<QGraphicsView *>("QGraphicsView*");

请务必在第一次使用此信号之前调用此函数。 虽然我不确定这是你所有问题的原因。

【讨论】:

QGraphicsView 是一个标准的 Qt 类。据我所知,我只需要以这种方式注册定制课程。 (我也从未在任何其他项目中使用内置类。)

以上是关于在 Qt 中使用信号会破坏 DLL的主要内容,如果未能解决你的问题,请参考以下文章

使用 MSYS 复制 System32 DLL 会破坏库的 64 位存在

Qt5 带有图层的涂鸦 - QPaintDevice:无法破坏正在绘制的设备

Qt:qthread在关闭期间线程仍在运行时被破坏

如何从 QML 连接 C++ 对象的破坏信号?

如何从 QML 连接 C++ 对象的破坏信号?

如何修复会破坏现有标签的问题