Qt使用QSharedMemory类操作共享内存段。把QSharedMemory看做一种指针,这种指针指向分配出来的一个共享内存段,这个共享内存段是由底层操作系统提供,可以供多个线程或进程使用。QSharedMemory不“拥有”共享内存段,当某一线程销毁QSharedMemory实例,或者所有线程都退出,WinDOWS内核会自动释放共享内存段。
共享数据
- 创建共享内存(指定内存区域大小和名字)
- 锁定共享内存
- 写入数据到共享内存
- 结束锁定共享内存
获取数据
- 连接共享内存(需要传入名字且与创建的内存区名字相同)
- 锁定共享内存
- 读取数据
- 解除锁定共享内存
- 断开连接
共享内存的实例如下:
首先是共享数据端:
#pragma once
#include <QtWidgets/QWidget>
#include <QTimer>
#include <QSharedMemory>
#include <QPixmap>
#include <QBuffer>
#include <QDataStream>
#include <QDebug>
#include <QFrame>
#include <QGridLayout>
#include <QPushButton>
#include <qmath.h>
#include "ui_ShareMemoryDemo1.h"
class ShareMemoryDemo1 : public QWidget
{
Q_OBJECT
public:
ShareMemoryDemo1(QWidget *parent = Q_NULLPTR);
private:
Ui::ShareMemoryDemo1Class ui;
const char* KEY_SHARED_MEMORY = "QSharedMemorydemo";
QSharedMemory* WshareMerary = nullptr;
QTimer* m_timer = nullptr;
QWidget* m_ShareWiget = nullptr;
QFrame* f = nullptr;
private:
void createFrame();
private slots:
void writeShareMeary();
};
#include "ShareMemoryDemo1.h"
#include <iostream>
#include <cstdint>
#include <stdint.h>
ShareMemoryDemo1::ShareMemoryDemo1(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
this->show();
this->resize(600, 400);
QFrame frame;
f = new QFrame;
createFrame();
f->show();
m_timer = new QTimer(this);
QSharedMemory shareMerary(KEY_SHARED_MEMORY);
//WshareMerary = &shareMerary;
WshareMerary = new QSharedMemory(KEY_SHARED_MEMORY, this);
connect(m_timer, SIGNAL(timeout()), this, SLOT(writeShareMeary()));
if (!WshareMerary->create(600 * 400 * 4))
{
qDebug() << WshareMerary->errorString();
return;
}
m_timer->start(100);
}
void ShareMemoryDemo1::writeShareMeary()
{
QPixmap _image = f->grab();
QBuffer buffer;
QDataStream out(&buffer);
buffer.open(QBuffer::ReadWrite);
out << _image;
int32_t size = buffer.size();
WshareMerary->lock();
uchar* to = static_cast<uchar*>(WshareMerary->data());
const char* from = buffer.data().constData();
if (to != nullptr && from != nullptr)
{
memcpy(to, &size, sizeof(int32_t));
memcpy(to + sizeof(int32_t), from, qMin(size, WshareMerary->size()));
}
WshareMerary->unlock();
}
void ShareMemoryDemo1::createFrame()
{
QGridLayout* layout = new QGridLayout;
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
layout->addWidget(new QPushButton(), i,j);
}
}
f->setWindowFlags(Qt::WindowCloseButtonHint);
f->setLayout(layout);
f->resize(600, 400);
f->show();
}
获取数据端:
#pragma once
#include <QtWidgets/QWidget>
#include <QTimer>
#include <QSharedMemory>
#include <QPixmap>
#include <QBuffer>
#include <QDataStream>
#include <QLabel>
#include <QDebug>
#include "ui_ShareMemoryDemo2.h"
class ShareMemoryDemo2 : public QWidget
{
Q_OBJECT
public:
ShareMemoryDemo2(QWidget *parent = Q_NULLPTR);
private:
Ui::ShareMemoryDemo2Class ui;
const char* KEY_SHARED_MEMORY = "QSharedMemorydemo";
QSharedMemory* merary = nullptr;
QTimer* m_timer = nullptr;
QWidget* m_ShareWiget = nullptr;
QLabel* RLabel = nullptr;
private slots:
void readShareMerary();
};
#include "ShareMemoryDemo2.h"
ShareMemoryDemo2::ShareMemoryDemo2(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
m_timer = new QTimer();
QSharedMemory RshareMemary(KEY_SHARED_MEMORY);
RLabel = new QLabel();
// merary = &RshareMemary;
merary = new QSharedMemory(KEY_SHARED_MEMORY, this);
RLabel->resize(600, 400);
RLabel->show();
connect(m_timer, SIGNAL(timeout()), this, SLOT(readShareMerary()));
m_timer->start(100);
}
void ShareMemoryDemo2::readShareMerary()
{
if (!merary->attach())
{
qDebug() << "error" << merary->errorString();
}
QBuffer buffer;
QDataStream in(&buffer);
QPixmap pixmap;
merary->lock();
int32_t size = 0;
const char* from = static_cast<const char*>(merary->constData());
memcpy(&size, from, sizeof(int32_t));
buffer.setData(from + sizeof(int32_t), size);
buffer.open(QBuffer::ReadWrite);
in >> pixmap;
buffer.close();
merary->unlock();
merary->detach();
RLabel->setPixmap(pixmap);
}
两个程序运行后效果如下: