-2

I am currently starting with QDBus. I am trying to send an int array of data to another programm which will do some calculations on the array and is supposed to send it back afterwards.

I tried just sending the array starting adress as an int. I believe the problem here is that I have to send a copy of the values somehow so my other prgoram doesn't ends up trying to mess with memory that isn't his.

I am currently getting this debug output:

sessionBus is connected...
Starting line conversion...
Done converting...
Data at:  -1077790240 
Reply invalid:  Message recipient disconnected from message bus without replying 
Starting line conversion...
Done converting...
Data at:  -1077790240 
Reply invalid:  The name domain.comSim was not provided by any .service files 
Starting line conversion...
Done converting...
Data at:  -1077790240 
Reply invalid:  The name domain.comSim was not provided by any .service files

From this code:

void MainWindow::on_btnSend_clicked()
{
    if (!QDBusConnection::sessionBus().isConnected())
    {
        qDebug() << "Cannot connect to the D-Bus session bus.\r\n";

        return;
    }

    qDebug() << "sessionBus is connected...\r\n";

    QDBusInterface iface(SERVICE_NAME, "/", "", QDBusConnection::sessionBus());

    if (iface.isValid())
    {
        int height = this->image->height();
        int width = this->image->width();

        for(int lineCounter = 0; lineCounter < height; lineCounter++)
        {
            qDebug() << "Starting line conversion...\r\n";

            QRgb* lineValues = (QRgb*)this->image->scanLine(lineCounter);

            /*

            QList<QVariant> args;

            args << QVariant::fromValue(width);

            for(int pixelCounter = 0; pixelCounter < width; pixelCounter++)
            {
                args << QVariant::fromValue(qAlpha(lineValues[pixelCounter]));
                args << QVariant::fromValue(qRed(lineValues[pixelCounter]));
                args << QVariant::fromValue(qGreen(lineValues[pixelCounter]));
                args << QVariant::fromValue(qBlue(lineValues[pixelCounter]));
                ]
            }*/


            int values[width][4];

            for(int c = 0; c < width; c++)
            {
                values[c][0] = qAlpha(lineValues[c]);
                values[c][1] = qRed(lineValues[c]);
                values[c][2] = qGreen(lineValues[c]);
                values[c][3] = qBlue(lineValues[c]);
            }

            qDebug() << "Done converting...\r\n";
            qDebug() << "Data at: " << (int)values << "\r\n";

            QDBusReply<int> reply = iface.call("processLine", (int)values, width);

            if (!reply.isValid())
            {
                qDebug() << "Reply invalid: " << qPrintable(reply.error().message()) << "\r\n";
            }
        }
    }
    else
    {
        qDebug() << "Interface is invalid: " << qPrintable(QDBusConnection::sessionBus().lastError().message());
    }
}

As you can see I also trie to box my values into a List of QVariants and tried to send this via callWithArgumentList but I haven't found a single example on how to write a signature that will handle these calls.

Currently my class that exports his slots looks like this:

class Simulation : public QObject
{
    Q_OBJECT

public slots:
    Q_SCRIPTABLE int processLine(int dataPtr, int length);
};

and "processLine" like this:

int Simulation::processLine(int dataPtr, int length)
{
    //int values[length][4];
    int** values = (int**)dataPtr;

    cout << "Data should be at: " << dataPtr << endl;

    cout << "Should start printing pixel values now:" << endl;

    for(int c = 0; c < length; c++)
    {
        cout << "Pixel #" << c << ": Alpha:" << values[c][0] << " Red:" << values[c][1] << " Green:" << values[c][2] << " Blue:" << values[c][3] << endl;
    }

    return dataPtr;
}

Which crashes after printing "Should start printing pixel values now:".

So my main question is what is a right and minimal way to tackle this problem (sending an int[] via dbus)?

Greetings, Robin

Robin B
  • 1,066
  • 1
  • 14
  • 32
  • Why don't you just send a `std::vector` or `QVector`? C-style arrays are nasty in so many ways.. – Jesper Juhl Jul 09 '17 at 16:48
  • I've tried with a QList and couldn't call "call" anymore cause there seemed to be some conversion into QVariant missing. But gonna try it with vector – Robin B Jul 09 '17 at 17:04
  • Same thing iface.call only accepts QVariant as parameters to pass onto the remote method and sadly there is no implicit conversion available for vector to QVariant – Robin B Jul 09 '17 at 17:11
  • Personally I've never had any problems sending a `QVector` or `std::vector` over dbus with Qt... But, if you are just missing a conversion to QVariant, then you could write such yourself - although I'm puzzled as to why you'd need to - it should be there already. – Jesper Juhl Jul 09 '17 at 17:13
  • That in fact a conversion was missing was an assumption based on that there is no overload found: error: no matching function for call to 'QDBusInterface::call(const char [12], std::vector >&)'. But if it worked for you there must be something even more obvious I'm missing here – Robin B Jul 09 '17 at 17:22
  • 1
    `int values[width][4];` is not valid C++. `iface.call("processLine", (int)values, width);` will (usually) pass only 32 bits of data to processLine. The problems you are reporting with QVariant come from a missing include (most likely you did not `#include ` – IlBeldus Jul 10 '17 at 13:13
  • Thanks so much for pointing these things out. I was now able to solve the issue by boxing a QList into QVariant (thanks to the include i was missing). – Robin B Jul 11 '17 at 19:15

1 Answers1

0

As it's most likely when you are starting with something your aren't familiar with the solution has been quite simple. One thing was to include QVariant

I am now able to transmit all data with the following code:

 if (iface.isValid())
    {
        int height = this->image->height();
        int width = this->image->width();        

        QImage* recvImage = new QImage(width, height, QImage::Format_ARGB32);

        for(int lineCounter = 0; lineCounter < height; lineCounter++)
        {
            qDebug() << "Starting line conversion...\r\n";

            QRgb* lineValues = (QRgb*)this->image->scanLine(lineCounter);

            QList<int> values;

            for(int c = 0; c < width; c++)
            {
                values.append(lineValues[c]);
                //values.append(qAlpha(lineValues[c]));
                //values.append(qRed(lineValues[c]));
                //values.append(qGreen(lineValues[c]));
                //values.append(qBlue(lineValues[c]));
            }

            QVariant arg;
            arg.setValue(values);

            QDBusReply<QList<int> > reply = iface.call("processLine", arg);

            if (!reply.isValid())
            {
                qDebug() << "Reply invalid: " << qPrintable(reply.error().message()) << "\r\n";
            }

            QList<int> recvValues = reply.value();
            QRgb* recvLineValues = (QRgb*)recvImage->scanLine(lineCounter);

            for(int c = 0; c < width; c++)
            {
                //int alpha = recvValues.at(4*c);
                //int red = recvValues.at(4*c);
                //int green = recvValues.at(4*c);
                //int blue = recvValues.at(4*c);
                //recvLineValues[c] = qRgba(red, green, blue, alpha);
                recvLineValues[c] = recvValues.at(c);
            }

            QGraphicsScene* scene = new QGraphicsScene();
            QGraphicsPixmapItem* item = new QGraphicsPixmapItem(QPixmap::fromImage(*(this->image)));

            scene->addItem(item);

            ui->gViewRecvImage->setScene(scene);
            ui->gViewRecvImage->show();

        }
    }
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Robin B
  • 1,066
  • 1
  • 14
  • 32