首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Qt官方示例-共享内存

Qt官方示例-共享内存

作者头像
Qt君
发布2023-03-17 14:58:11
发布2023-03-17 14:58:11
1.6K0
举报
文章被收录于专栏:跟Qt君学编程跟Qt君学编程

这个例子展示了如何使用QSharedMemory类(共享内存)进行进程间通信。

  构建示例,请运行make。要运行该示例,请运行两个实例。main()函数创建一个应用程序和我们示例的Dialog类的实例。显示对话框,然后将控制以标准方式传递给应用程序。

代码语言:javascript
复制
int main(int argc, char *argv[])
{
    QApplication application(argc, argv);
    Dialog dialog;
    dialog.show();
    return application.exec();
}

  展示Dialog类的两个实例。共享内存示例的屏幕截图👇

共享内存示例的屏幕截图

  Dialog类继承QDialog。它封装了用户界面和QSharedMemory实例。它还具有两个公有槽函数,分别是loadFromFile()loadFromMemory(),它们对应于对话框上的两个按钮。

代码语言:javascript
复制
class Dialog : public QDialog
{
    Q_OBJECT

  public:
    Dialog(QWidget *parent = nullptr);

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

 private:
    void detach();

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

  构造函数将构建用户界面小部件,并将每个按钮的clicked()信号连接到相应的槽函数。

代码语言:javascript
复制
Dialog::Dialog(QWidget *parent)
  : QDialog(parent), sharedMemory("QSharedMemoryExample")
{
    ui.setupUi(this);
    connect(ui.loadFromFileButton, &QPushButton::clicked,
            this, &Dialog::loadFromFile);
    connect(ui.loadFromSharedMemoryButton, &QPushButton::clicked,
            this, &Dialog::loadFromMemory);
    setWindowTitle(tr("SharedMemory Example"));
}

请注意,"QSharedMemoryExample"将传递给QSharedMemory()构造函数以用作键值。系统会将其用作基础共享内存段的标识符。

  单击Load Image From File...按钮,会调用loadFromFile()槽函数。首先,它测试共享内存段是否已附加到该进程。如果是这样,则该段将从过程中分离出来,因此可以确保我们正确地开始执行该示例。

代码语言:javascript
复制
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));

  然后要求用户使用QFileDialog::getOpenFileName()选择图像文件。所选文件被加载到QImage中。使用QImage可以确保所选文件是有效图像,还可以使用setPixmap()在对话框中立即显示该图像。

  接下来,使用QDataStream将图像流式传输到QBuffer中。设置大小,然后我们将其用于create()我们的共享内存段。创建共享内存段会自动将该段附加到进程。在这里使用QBuffer可使我们获得指向图像数据的指针,然后将其用于从QBuffer到共享内存段的memcopy()

代码语言:javascript
复制
    // load into shared memory
    QBuffer buffer;
    buffer.open(QBuffer::ReadWrite);
    QDataStream out(&buffer);
    out << image;
    int size = buffer.size();

    if (!sharedMemory.create(size)) {
        ui.label->setText(tr("Unable to create shared memory segment."));
        return;
    }
    sharedMemory.lock();
    char *to = (char*)sharedMemory.data();
    const char *from = buffer.data().data();
    memcpy(to, from, qMin(sharedMemory.size(), size));
    sharedMemory.unlock();
}

  请注意,在复制到共享内存段之前,我们先对其进行lock(),然后在复制后立即再次对其进行unlock()。这样可以确保我们拥有对共享内存段的独占访问权来执行我们的memcopy()。如果某个其他进程具有段锁,则我们的进程将阻塞,直到该锁可用为止。

  还要注意,该函数不会在memcopy()unlock()之后从共享内存段中detach()。回想一下,当最后一个进程从共享内存段中分离时,该段将由操作系统释放。由于此过程目前仅连接到共享内存段,因此,如果loadFromFile()从共享内存段分离,则该段将被销毁,然后再进行下一步。

  函数返回时,如果您选择的文件是qt.png,则第一个对话框如下所示。

代码语言:javascript
复制
void Dialog::loadFromMemory()
{
    if (!sharedMemory.attach()) {
        ui.label->setText(tr("Unable to attach to shared memory segment.\n" \
                             "Load an image first."));
        return;
    }

    QBuffer buffer;
    QDataStream in(&buffer);
    QImage image;

    sharedMemory.lock();
    buffer.setData((char*)sharedMemory.constData(), sharedMemory.size());
    buffer.open(QBuffer::ReadOnly);
    in >> image;
    sharedMemory.unlock();

    sharedMemory.detach();
    ui.label->setPixmap(QPixmap::fromImage(image));
}

  在这种情况下,该函数会从该段执行detach(),因为现在我们已经有效地完成了对它的使用。最后,显示QImage。此时,两个对话框都应显示相同的图像。当关闭第一个对话框时,对话框析构函数调用QSharedMemory析构函数,该析构函数与共享内存段分离。由于这是要从该段分离的最后一个进程,因此操作系统现在将释放共享内存。

关于更多

  • QtCreator软件可以找到:
  • 或在 以下Qt安装目录找到:
代码语言:javascript
复制
C:\Qt\{你的Qt版本}\Examples\{你的Qt版本}\corelib\ipc\sharedmemory
  • 相关链接
代码语言:javascript
复制
https://doc.qt.io/qt-5/qtcore-ipc-sharedmemory-example.html
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Qt君 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于更多
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档