Question

I'd like to send a custom c++ class through the Qt DBUS API. I've created the class from the .proto file using the protoc compiler and added them to my project in QtCreator. Now I want to verify that I can send the custom class as a QVariant through the dbus API. I have a receiver and sender program and can send a simple test string so Dbus works. I am having trouble sending the protocol buffer class after adding it as a metatypes.

My test .proto file contains only ints:

message MyData {
  required int32 name = 1;
  required int32 id = 2;
  optional int32 email = 3;
}

To the protocol buffer class header file I added:

#include <QMetaType>
#include <QDBusMetaType>
...
friend QDBusArgument &operator<<(QDBusArgument &argument, const MyData &dataToWrite);
friend const QDBusArgument &operator>>(const QDBusArgument &argument, MyData &dataToWrite);
...
Q_DECLARE_METATYPE(MyData )

And to the protocol buffer class implementation file I added:

#include <QDebug>
...
#include <QMetaType>
#include <QDBusMetaType>

// Marshall the MyData data into a D-Bus argument
QDBusArgument &operator<<(QDBusArgument &argument, const MyData &dataToWrite)
{

    qDebug() << "OPERATOR<<";

    argument.beginStructure();

    // Break out the various properties of dataToWrite protocol buffer
    int name = dataToWrite.name();
    int id = dataToWrite.id();
    int email = dataToWrite.email();
    qDebug() << name;
    qDebug() << id;
    qDebug() << email;

    argument << name;
    argument << id;
    argument << email;
    argument.endStructure();
    return argument;

}

// Retrieve the MyData data from the D-Bus argument
const QDBusArgument &operator>>(const QDBusArgument &argument, MyData &dataToWrite)
{

    qDebug() << "OPERATOR>>";

    argument.beginStructure();

    // Break out the various properties of dataToWrite protocol buffer
    int name = dataToWrite.name();
    int id = dataToWrite.id();
    int email = dataToWrite.email();
    qDebug() << name;
    qDebug() << id;
    qDebug() << email;

    argument >> name;
    argument >> id;
    argument >> email;
    argument.endStructure();
    return argument;

}

Main simply looks like this:

QCoreApplication a(argc, argv);

    dbussender* client = new dbussender("com.one.two.three.nvram", "/dbusReadWriteNvRam", QDBusConnection::sessionBus(), 0);

    // Create a protocol buffer class and provide its properties with values
    MyData dataToWrite;
    dataToWrite.set_name(2);
    dataToWrite.set_id(3);
    dataToWrite.set_email(4);

    QString command3 = "Contacting Protobuf Receiver and calling WRITENVRAM...";
    QString response3 = client->writeNVRam(dataToWrite);

    std::cout << "Command:   " << command3.toStdString() << std::endl;
    std::cout << "Response:   " << response3.toStdString() << std::endl;

My dbussender class calls the remote function like this:

inline QDBusPendingReply<QString> writeNVRam(MyData dataToWrite)
    {

        qDebug() << "Sending " << dataToWrite.name();
        qDebug() << "Sending " << dataToWrite.id();
        qDebug() << "Sending " << dataToWrite.email();

        QList<QVariant> argumentList;
        argumentList << QVariant::fromValue<MyData>(dataToWrite);
        return asyncCallWithArgumentList(QLatin1String("writeNVRam"), argumentList);
    }

Ultimately in my receiver program, this function is called but always returns 0:

// Write NVRAM
QString dbusReadWriteNvRam::writeNVRam(MyData dataToWrite) {

    qDebug() << "WRITE NVRAM COMMAND CALLED";

    qDebug() << "Unpacking: " << dataToWrite.name();
    qDebug() << "Unpacking: " << dataToWrite.id();
    qDebug() << "Unpacking: " << dataToWrite.email();

    return "HELLO CLASS";

}

Here is the output of the Sender program:

Sending  2 
Sending  3 
Sending  4 
OPERATOR<< 
0 
0 
0 
OPERATOR<< 
2 
3 
4 
Command:   Contacting Protobuf Receiver and calling WRITENVRAM...
Response:   HELLO CLASS

And here is the output of the Receiver program:

OPERATOR<< 
0 
0 
0 
OPERATOR>> 
0 
0 
0 
WRITE NVRAM COMMAND CALLED 
Unpacking:  0 
Unpacking:  0 
Unpacking:  0

Why does it seem that the marshalling functions are being called twice? And howcome the second call seems to include the valid values of 2,3,4 for the 3 properties of my protocol buffer but the first call is all 0's? The Receiver only seems to see the All 0's and never receives a protocol buffer object with valid values.

Is there something wrong with my marshalling code? What else could be going on?

Was it helpful?

Solution

To make this work, implement the operators like so:

// PROTOBUF-MODIFICATION-DBUS
// Marshall the companyData data into a D-Bus argument
QDBusArgument &operator<<(QDBusArgument &argument, const companyData &dataToWrite)
{

    argument.beginStructure();

    // Break out the various properties of dataToWrite protocol buffer
    int name = dataToWrite.name();
    int id = dataToWrite.id();
    int email = dataToWrite.email();
    argument << name;
    argument << id;
    argument << email;
    argument.endStructure();
    return argument;

}

// PROTOBUF-MODIFICATION-DBUS
// Retrieve the companyData data from the D-Bus argument
const QDBusArgument &operator>>(const QDBusArgument &argument, companyData &dataToWrite)
{

    int name, id, email;

    argument.beginStructure();
    argument >> name;
    argument >> id;
    argument >> email;
    argument.endStructure();
    dataToWrite.set_name(name);
    dataToWrite.set_id(id);
    dataToWrite.set_email(email);
    return argument;

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top