c++qtqmlqtremoteobjects

Unable to connect using QML Remote Object with Error: "connectionToSource is null"


I am trying to use Qt Remote Objects for creating client server application. But encountered an issue that says "connectionToSource is null". How do I set the source connection ?

I am creating the server using the .rep file. The code I had used is as follows:

Data Model

// Rep File (DataModel.rep)
class DataModel {
    PROP(double data)
}

Server Code

// DataBroadcaster class (DataBroadcaster.h)
// DataBroadcaster class inherits DataModelSimpleSource.h (generated from .rep file)    
    #include "rep_DataModel_Source.h"
    class DataBroadcaster : public DataModelSimpleSource
    {
        Q_OBJECT
        public:
            DataBroadcaster(QObject *parent = nullptr);
            ~DataBroadcaster();
        void Initialize();
            private:
            int QScopedPointer<QRemoteObjectHost> remoteHost;
    }

// DataBroadcaster.cpp

DataBroadcaster::DataBroadcaster(QObject *parent): DataModelSimpleSource(parent){}
DataBroadcaster::~DataBroadcaster(){}
void DataBroadcaster::Initialize()
{
    remoteHost.reset(new QRemoteObjectHost(QUrl(QStringLiteral("local:mydata"))));
    remoteHost->enableRemoting(this, "DataModel");
}

// Server code main function

#include <QCoreApplication>
#include "DataBroadcaster.h"
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    DataBroadcaster server;
    server.Initialize();    
    double count = 0.0;
    while(true)
    {
        server.pushData(count + 0.1);
    }   
    return a.exec();
}

Client Code

// DataModelDataReplica is generated from .rep file used to generate source
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>

#include "rep_DataModel_replica.h"

int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    // registered as qml type in main
    qmlRegisterType<DataModelReplica>("CustomData", 1, 0, "MyData");
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);
    return app.exec();
}

QML Code

// DisplayPage.qml Added to QML file    
import CustomData 1.0    
MyData {
    id: dataClient
    node: Node {
        registerUrl: "local:mydata"
    }
    Button {
        id: btn
        text: "Server Data" 
        onClicked: {
            // displaying some data from source
            btn.text = dataClient.data
        }
    }
}

Execution:

Server code is running
Client code is running but when trying to get data I get following error message in debugger
**"qt.remoteobjects: connectionToSource is null"**

I am unable to figure out what am I missing. If anyone has any idea about how to resolve or where to look for please suggest.


Solution

  • I was able to find the problem. In the Server Code main function, the while loop is used which never exits because of which the "exec()" function was never called and Qt event loop never started because of which the Qt Remote object didn't share data. So I changed the following code using the Signal and Slot mechanism to create a non-blocking function. Following is the code change that I made.

    // Server Code main function

    #include <QCoreApplication>
    #include "DataBroadcaster.h"
    #include "ServerController.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        DataBroadcaster server;
        server.Initialize(); 
        ServerController controller(&server);
        return a.exec();
    }
    

    // Server Controller

    #include <QTimer>
    #include "DataBroadcaster.h"
    
    class ServerController : public QObject
    {
    Q_OBJECT
    public:
        explicit ServerController(QObject *parent = nullptr, DataBroadcast *server = nullptr);
        ~ServerController();
    
    public Q_SLOTS:
        void SendData();
    
    private:
        QTimer timer;
        double count = 0.0; 
        DataBroadcast *m_server = nullptr;
    }
    
    ServerController::ServerController(QObject *parent, DataBroadcast *server): QObject(parent), m_server(server)
    {
        connect(&timer, SIGNAL(timeout()), this, SLOT(SendData()));
        timer.start();
    }
    
    ServerController::~ServerController()
    {
        timer.stop();
    }
    
    ServerController::SendData()
    {
        count += 0.1;
        if(m_server != nullptr)
        {
             m_server->pushData(count);
        }
    }