0

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.

ralgrad
  • 29
  • 10

2 Answers2

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);
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • Thanks this helped to narrow the issue down. I forgot to add that the signal is initially declared in an Interface that the Parent class implements. If I add this I get the issue again. Without the Interface it works. We are probably gonna move the interface to the Parent class and see if that works. – ralgrad Aug 26 '16 at 09:31
  • @ralgrad That's what you get for not posting a test case, tsk tsk. You may wish to look at the answers to [this question](http://stackoverflow.com/q/17943496/1329652). – Kuba hasn't forgotten Monica Aug 26 '16 at 13:00
  • I made a copy of the sigslot folder, added some code according to the linked question and its answer, but I still get the issue. You can find it here: https://github.com/madmason/sigslot-dll/tree/master I hope the credit/link to your repo is good enough as credit. – ralgrad Aug 29 '16 at 08:30
0

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.

ralgrad
  • 29
  • 10