signal not correctly exported when inheriting from

2019-09-11 02:00发布

问题:

The following situation: I have a class (Parent) in DLL A which has a signal (which is final). I have a class (Child) in DLL B that inherits from A. I import both DLLs to my project. Then I have a class in my project get an instance of the Child class and try to connect the signal of the Child instance to the current object. Somehow this connection fails. Running the whole thing in debug mode only gives me: QObject::connect: signal not found in Child. Checking the dumpbin shows me that the signal is in DLL A but not in DLL B. Both the class Parent and the class Child have the proper export statements but somehow the the signal for the Child class doesn't get exported. Here is the whole thing as code:

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 in project:

    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
            }
    }

So the problem seems to be somewhere is the proper export of everything in the DLL B but I can't figure out how to do it. Any help would be appreciated.

回答1:

I'm sorry, but I can't reproduce this issue on either Windows 10.0 with MSVC2015 and Qt 5.7 or OS X 10.10. Please try this project verbatim and see if it works for you. If it does, you're doing something else wrong and will need to produce a test case and edit it into the question.

The project is available from: 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);
}


回答2:

So the issue seems to be somewhere with the usage of the Interface. We solved the issue for now by moving everything from the ParentInterface into the Parent class and removing the ParentInterface. This feels more like a workaround than a proper solution though.



标签: c++ qt dll