【问题标题】:signal not correctly exported when inheriting from different dll从不同的 dll 继承时信号未正确导出
【发布时间】:2016-08-25 15:31:07
【问题描述】:

以下情况: 我在 DLL A 中有一个类(Parent),它有一个信号(这是最终的)。我在 DLL B 中有一个继承自 A 的类 (Child)。我将两个 DLL 都导入到我的项目中。然后我的项目中有一个类获取Child 类的实例,并尝试将Child 实例的信号连接到当前对象。不知何故,这种连接失败了。在调试模式下运行整个事情只会给我:QObject::connect: signal not found in Child。检查转储箱显示信号在 DLL A 中,但不在 DLL B 中。Parent 类和Child 类都有正确的导出语句,但不知何故,Child 类的信号没有得到出口。这是代码的全部内容:

a.dll:

    class DLLA_SHAREDEXPORT ParentInterface{
    public:
        ~ParentInterface(){}
        virtual void test() = 0;
    };
    Q_DECLARE_INTERFACE(ParentInterface, "ParentInterface")

    class DLLA_SHAREDEXPORT Parent : public QObject,
        public ParentInterface{
        Q_OBJECT
        Q_INTERFACES(ParentInterface)
    ...
    signals:
        void test();

    }

b.dll:

    class DLLB_SHAREDEXPORT Child : public Parent{
        Q_OBJECT
    ...
    }

项目中的类:

    class SomeClass : public QObject{
        Q_OBJECT
    public:
            ...
            void someFunction(){
                Parent* c = getChildObject(); //some call to get the Object of class Child
                QObject::connect(c, &Parent::test,
                         this, &SomeClass::handle_test); 
                //QObject::connect: signal not found in Child
            }
    }

    public slots:
            void handle_test(){
                //do something
            }
    }

所以问题似乎出在某个地方,是 DLL B 中所有内容的正确导出,但我不知道该怎么做。任何帮助将不胜感激。

【问题讨论】:

    标签: c++ qt dll


    【解决方案1】:

    很抱歉,我无法在带有 MSVC2015 和 Qt 5.7 的 Windows 10.0 或 OS X 10.10 上重现此问题。请逐字尝试这个项目,看看它是否适合你。如果是这样,那么您做错了什么,需要生成一个测试用例并将其编辑到问题中。

    该项目来自:https://github.com/KubaO/stackoverflown/tree/master/questions/sigslot-dll-39149263

    sigslot-dll-39149263.pro

    TEMPLATE = subdirs
    SUBDIRS += lib1 lib2 main
    main.depends += lib1 lib2
    lib2.depends += lib1
    

    lib1/lib1.pro

    QT = core
    CONFIG += c++11
    TEMPLATE = lib
    HEADERS += lib1.h
    win32:DEFINES += LIB1_EXPORT=__declspec(dllexport)
    

    lib1/lib1.h

    #ifndef LIB1_H
    #define LIB1_H
    
    #include <QObject>
    
    #ifdef WIN32
    #ifndef LIB1_EXPORT
    #define LIB1_EXPORT __declspec(dllimport)
    #endif
    #else
    #define LIB1_EXPORT
    #endif
    
    class LIB1_EXPORT Parent : public QObject {
        Q_OBJECT
    public:
        Q_SIGNAL void test();
    };
    
    #endif
    

    lib2/lib2.pro

    QT = core
    CONFIG += c++11
    TEMPLATE = lib
    HEADERS += lib2.h
    win32:DEFINES += LIB2_EXPORT=__declspec(dllexport)
    win32:CONFIG(debug,release|debug) LIBSUBPATH=/debug
    win32:CONFIG(release,release|debug) LIBSUBPATH=/release
    LIBS += -L../lib1$$LIBSUBPATH -llib1
    INCLUDEPATH += ..
    DEPENDPATH += ..
    

    lib2/lib2.h

    #ifndef LIB2_H
    #define LIB2_H
    
    #include "lib1/lib1.h"
    
    #ifdef WIN32
    #ifndef LIB2_EXPORT
    #define LIB2_EXPORT __declspec(dllimport)
    #endif
    #else
    #define LIB2_EXPORT
    #endif
    
    class LIB2_EXPORT Child : public Parent {
        Q_OBJECT
    };
    
    #endif
    

    main/main.pro

    QT = core
    CONFIG += c++11
    TEMPLATE = app
    SOURCES += main.cpp
    win32:CONFIG(debug,release|debug) LIBSUBPATH=/debug
    win32:CONFIG(release,release|debug) LIBSUBPATH=/release
    LIBS += -L../lib1$$LIBSUBPATH -llib1 -L../lib2$$LIBSUBPATH -llib2
    INCLUDEPATH += ..
    DEPENDPATH += ..
    

    main/main.cpp

    #include "lib1/lib1.h"
    #include "lib2/lib2.h"
    
    int main() {
        int counter = 0;
        Child child;
        Parent * parent = &child;
        QObject::connect(parent, &Parent::test, [&]{ counter++; });
        emit parent->test();
        emit parent->test();
        Q_ASSERT(counter == 2);
    }
    

    【讨论】:

    • 感谢这有助于缩小问题范围。我忘了补充一点,信号最初是在父类实现的接口中声明的。如果我添加这个,我会再次遇到问题。没有接口它就可以工作。我们可能会将接口移至 Parent 类,看看是否可行。
    • @ralgrad 这就是你没有发布测试用例的结果,啧啧啧。你不妨看看this question的答案。
    • 我复制了 sigslot 文件夹,根据链接的问题及其答案添加了一些代码,但我仍然遇到问题。你可以在这里找到它:github.com/madmason/sigslot-dll/tree/master我希望你的回购的信用/链接足以作为信用。
    【解决方案2】:

    所以问题似乎出在接口的使用上。我们现在通过将所有内容从 ParentInterface 移动到 Parent 类并删除 ParentInterface 来解决这个问题。不过,这感觉更像是一种解决方法,而不是适当的解决方案。

    【讨论】:

      猜你喜欢
      • 2013-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      相关资源
      最近更新 更多