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.
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);
}
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.