QObject::connect: Cannot connect (null)::mySignal() to (null)::mySlot()

非 Y 不嫁゛ 提交于 2019-12-08 10:48:58

问题


I'm missing the point while trying to connect signal/slots between plugins. Considering this question I've made the following.

I'll be presenting the full source code of 3 Qt projects:

  • pluginTCP: A plugin
  • pluginRaw: Another plugin
  • platform: The platform using the plugins

pluginTcp.pro

TEMPLATE        = lib
CONFIG         += plugin

CONFIG(debug, debug | release) {
    DESTDIR = debug
} else {
    DESTDIR = release
}

OBJECTS_DIR = $$DESTDIR
    MOC_DIR = $$DESTDIR
    RCC_DIR = $$DESTDIR
     UI_DIR = $$DESTDIR

QMAKE_CXXFLAGS += -std=c++0x

HEADERS         = ../../plugins/plugininterface.h \
                  ../tcpplugin.h

SOURCES         = ../tcpplugin.cpp

TARGET          = $$qtLibraryTarget(tplugin)
DESTDIR         = ../../plugins

plugininterface.h

class PluginInterface
{
public:
    virtual ~PluginInterface() {}

signals:
    virtual void mySignal() = 0;

public slots:
    virtual void mySlot() = 0;
};

#define PluginInterface_iid "org.qt-project.Qt.Examples.PluginInterface"
Q_DECLARE_INTERFACE(PluginInterface, PluginInterface_iid)

tcpplugin.h

#include <QObject>

#include "../plugins/plugininterface.h"

class QLineEdit;

class TcpPlugin : public QObject, PluginInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PluginInterface" /*FILE "echoplugin.json"*/)
    Q_INTERFACES(PluginInterface)

public:
    TcpPlugin();

signals:
    void mySignal() Q_DECL_FINAL;

public slots:
    void mySlot() Q_DECL_OVERRIDE;
};

tcpplugin.h

#include "tcpplugin.h"

TcpPlugin::TcpPlugin()
{
}

void TcpPlugin::mySlot()
{

}

pluginRaw.pro

TEMPLATE        = lib
CONFIG         += plugin

CONFIG(debug, debug | release) {
    DESTDIR = debug
} else {
    DESTDIR = release
}

OBJECTS_DIR = $$DESTDIR
    MOC_DIR = $$DESTDIR
    RCC_DIR = $$DESTDIR
     UI_DIR = $$DESTDIR

QMAKE_CXXFLAGS += -std=c++0x

HEADERS         = ../../plugins/plugininterface.h \
                  ../rawplugin.h

SOURCES         = ../rawplugin.cpp

TARGET          = $$qtLibraryTarget(rawplugin)
DESTDIR         = ../../plugins

rawplugin.h

#include <QObject>

#include "../plugins/plugininterface.h"

class RawPlugin : public QObject, PluginInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.PluginInterface" /*FILE "echoplugin.json"*/)
    Q_INTERFACES(PluginInterface)

public:
    RawPlugin();

signals:
    void mySignal() Q_DECL_FINAL;

public slots:
    void mySlot() Q_DECL_OVERRIDE;
};

rawplugin.cpp

#include "rawplugin.h"

RawPlugin::RawPlugin()
{
}

void RawPlugin::mySlot()
{

}

platform.pro

QT += core widgets

TEMPLATE = app

CONFIG(debug, debug | release) {
    DESTDIR = debug
} else {
    DESTDIR = release
}

OBJECTS_DIR = $$DESTDIR
    MOC_DIR = $$DESTDIR
    RCC_DIR = $$DESTDIR
     UI_DIR = $$DESTDIR

QMAKE_CXXFLAGS += -std=c++0x

HEADERS += ../../plugins/plugininterface.h \
           ../mainwindow.h

SOURCES += ../main.cpp \
          ../mainwindow.cpp

main.cpp

#include <QApplication>

#include "mainwindow.h"

int main(int argv, char *args[])
{
    QApplication app(argv, args);

    MainWindow window;
    window.show();

    return app.exec();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include "../../plugins/plugininterface.h"

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);

private:
    PluginInterface *loadPlugin(const QString name);
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"

#include <QDir>
#include <QPluginLoader>
#include <QApplication>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    PluginInterface *t = loadPlugin("tplugind.dll");
    PluginInterface *r = loadPlugin("rawplugind.dll");

    connect(dynamic_cast<QObject*>(t), SIGNAL(mySignal()),
            dynamic_cast<QObject*>(r), SLOT(mySlot()));
}


PluginInterface *MainWindow::loadPlugin(const QString name)
{
    PluginInterface *p;
    QDir pluginsDir(qApp->applicationDirPath());

    if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release")
        pluginsDir.cdUp();

    pluginsDir.cd("../../plugins");
    QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(name));
    QObject *plugin = pluginLoader.instance();
    if (plugin)
        p = qobject_cast<PluginInterface *>(plugin);
    return p;
}

It seems the dynamic_cast<QObject*>is returning null. Why?


回答1:


I'm too lazy to compile such a long project, but I see one reason why your code won't work and why you're getting a null pointer from the cast.

In your plugins you use inheritance

class RawPlugin : public QObject, PluginInterface

which is equivalent to

class RawPlugin : public QObject, private PluginInterface

This means your base class PluginInterface is inaccessible and dynamic_cast or qobject_cast will fail.

The fix is easy:

class RawPlugin : public QObject, public PluginInterface


来源:https://stackoverflow.com/questions/36121270/qobjectconnect-cannot-connect-nullmysignal-to-nullmyslot

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!