Shared Memory Example

The Shared Memory example shows how to use the QSharedMemory class to implement inter-process communication using shared memory. To build the example, run make. To run the example, start two instances of the executable. The main() function creates an application and an instance of our example's Dialog class. The dialog is displayed and then control is passed to the application in the standard way.

 
Sélectionnez
int main(int argc, char *argv[])
{
    QApplication application(argc, argv);
    Dialog dialog;
    dialog.show();
    return application.exec();
}

Two instances of class Dialog appear.

Screenshot of the Shared Memory example

Class Dialog inherits QDialog. It encapsulates the user interface and an instance of QSharedMemory. It also has two public slots, loadFromFile() and loadFromMemory() that correspond to the two buttons on the dialog.

 
Sélectionnez
class Dialog : public QDialog
{
    Q_OBJECT

  public:
    Dialog(QWidget *parent = 0);

  public slots:
    void loadFromFile();
    void loadFromMemory();

 private:
    void detach();

  private:
    Ui::Dialog ui;
    QSharedMemory sharedMemory;
};

The constructor builds the user interface widgets and connects the clicked() signal of each button to the corresponding slot function.

 
Sélectionnez
Dialog::Dialog(QWidget *parent)
  : QDialog(parent), sharedMemory("QSharedMemoryExample")
{
    ui.setupUi(this);
    connect(ui.loadFromFileButton, SIGNAL(clicked()), SLOT(loadFromFile()));
    connect(ui.loadFromSharedMemoryButton,
            SIGNAL(clicked()),
            SLOT(loadFromMemory()));
    setWindowTitle(tr("SharedMemory Example"));
}

Note that "QSharedMemoryExample" is passed to the QSharedMemory() constructor to be used as the key. This will be used by the system as the identifier of the underlying shared memory segment.

Click the Load Image From File... button on one of the dialogs. The loadFromFile() slot is invoked. First, it tests whether a shared memory segment is already attached to the process. If so, that segment is detached from the process, so we can be assured of starting off the example correctly.

 
Sélectionnez
void Dialog::loadFromFile()
{
    if (sharedMemory.isAttached())
        detach();

    ui.label->setText(tr("Select an image file"));
    QString fileName = QFileDialog::getOpenFileName(0, QString(), QString(),
                                        tr("Images (*.png *.xpm *.jpg)"));
    QImage image;
    if (!image.load(fileName)) {
        ui.label->setText(tr("Selected file is not an image, please select another."));
        return;
    }
    ui.label->setPixmap(QPixmap::fromImage(image));

The user is then asked to select an image file using QFileDialog::getOpenFileName(). The selected file is loaded into a QImage. Using a QImage lets us ensure that the selected file is a valid image, and it also allows us to immediately display the image in the dialog using setPixmap().

Next the image is streamed into a QBuffer using a QDataStream. This gives us the size, which we then use to create() our shared memory segment. Creating a shared memory segment automatically attaches the segment to the process. Using a QBuffer here lets us get a pointer to the image data, which we then use to do a memcopy() from the QBuffer into the shared memory segment.

 
Sélectionnez