1 year ago

#71527

test-img

ddgg

Share an instance of a QMainWindow through shared memory

Is it possible to share an instance of an QMainWindow (or a QWidget) through QSharedMemory?

I have been looking for some examples, and as far as I understood the problem seems to be that the QDataStream&operator>> doesn't know how to deserialise a QObject...right?

here my attempt: I serialise and copy the instance of my MainWindow into the shared memory

void MainWindow::loadIntoMemory()
{
    ...
    QBuffer buffer;
    buffer.open(QBuffer::WriteOnly);
    QDataStream out(&buffer);
    ... // omitting - if this == nullptr -
    out << this; // <-- serialising the MainWindow
    int size = buffer.size();
    sharedMemory.create(size)); // omitting if statement to avoid post verbosity
    sharedMemory.lock();
    char *to = (char*)sharedMemory.data();
    const char *from = buffer.data().data();
    memcpy(to, from, qMin(sharedMemory.size(), size));
    ...
}

but it comes to deserialise it from another app:

QMainWindow parentApp;
QBuffer buffer;
QDataStream in(&buffer); 
in >> parentApp;

I got the error: error: invalid operands to binary expression ('QDataStream' and 'QMainWindow') qchar.h:663:28: note: candidate function not viable: no known conversion from 'QMainWindow' to 'QChar &' for 2nd argument.

I have been also considering that maybe sharing the memory address of this could be an option. Something like:

  • saving this (a QMainWindow*) as a QbitArray`
  • serialise it
  • copying into the shared memory and load it from another application

but I wouldn't know how to do it...

EDIT The ultimate goal of this Application would be the following: The Application "A" (the one reading from the shared memory) is a child process (QProcess) of Application "B" (the one writing into the shared memoery). Application "A" is able to dynamically instantiate QDockWidgets which should dock onto the MainWindow of Application "B".

Since I cannot access any parent element from a child process, I was considering to share the Application "B"'s MainWindow from a shared memory and instantiate:

QDockWidget dock = new QDockWidget(parentAppMainWindow) // pointer red from the QSharedMemory

EDIT (second step):

As suggested by @G.M. one possible approach is to exchange the window id by (in this case) a shared memory. So I refactored the above presented loadIntoMemoryfunction so that "Application B" (the parent) shared its MainWindow'id into the shared memory :

void MainWindow::loadIntoMemory() // from application B
{
    // I instantiate "out" as QDataStream using the QBuffer buffer (Write only)
    ...
    WId id = this->winId();
    out << id; // <-- serialize id into the QDataStream
    qDebug() << id // print the id
    ...
    // calculate the size of the buffer and memcpy buffer into the 
}

then I read the value from sharedMemory from Application A (the child Qprocess of Application B as follows:

WId parentWinId;
QBuffer buffer;
QDataStream in(&buffer);  // read the id
sharedMemory.lock();
buffer.setData((char*)sharedMemory.constData(), sharedMemory.size());
buffer.open(QBuffer::ReadOnly);
in >> parentWinId;
sharedMemory.unlock();
qDebug() <<"The parent window Id is" << parentWinId; // parentWinId has exactly the same id as in the previous code block
qDebug() << "Here a representation of the parent window " << QWindow::fromWinId(parentWinId); // CRASH

but "Application A" crashes.

Thank you very much for your support!

c++

qt

shared-memory

0 Answers

Your Answer

Accepted video resources