QT 进程间通信之古老的方法(内存共享)

转载:https://blog.csdn.net/wangyeqiang/article/details/8296930

Qt提供了一种安全的共享内存的实现QSharedMemory,以便在多线程和多进程编程中安全的使用。比如说QQ的聊天的客户端,这里有个个性头象,当点击QQ音乐播放器的时候,启动QQ音乐播放器(启动一QQ音乐播放器的进程)这时QQ音乐播放器里也有一个个性头像,这两者间的头像一样,现用共享内存的方法实现。

    先说下实现共享内存的步骤,然后用一具体的实例说明。

向共享内存中提供数据的一方:

    1,定义QSharedMemory shareMemory,并设置标志名shareMemory.setKey();

     2,将共享内存与主进程分离 shareMemory.detach();

    3,创建共享内存 shareMemory.create();

     4,将共享内存上锁shareMemory.lock();

     5,将进程中要共享的数据拷贝到共享内存中;

     6,将共享内存解锁shareMemory.unlock();

从共享内存中取数据的一方:

    1,定义QSharedMemory shareMemory,并设置共享内存的标志名shareMemory.setKey()注意设置的要与提供内存共享的一方要一样。

    2,将共享内存上锁shareMemory.lock();

    3,将共享内存与主进程绑定shareMemory.attach(),使该进程可以访问共享内存的数据;

    4,从共享内存中取数据;

    5,使用完后将共享内存解锁shareMemory.unlock(),另外将共享内存与该进程分离shareMemory.detach();


下面贴段代码来说明:

A 向共享内存中提供数据的一方

main.cpp
#include <QtGui/QApplication>
#include "widget.h"
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();  
    return a.exec();
}
 
widget.h
ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include <QSharedMemory>
 
namespace Ui {
class Widget;
}
 
class Widget : public QWidget
{
    Q_OBJECT
    
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    
private slots:
    void on_pushButton_clicked();
 
    void on_pushButton_2_clicked();
 
private:
    Ui::Widget *ui;
    QSharedMemory shareMemory;//注意该变量不要在函数内局部定义,由于函数内的局部变量随着函数执行结束而消失
};
 
#endif // WIDGET_H
widget.cpp
 
#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QBuffer>
#include <QDebug>
#include <QProcess>
 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    shareMemory.setKey("share");
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::on_pushButton_clicked()
{
    if(shareMemory.isAttached())
    {
        shareMemory.detach();//将该进程与共享内存段分离
    }
    QString filename = QFileDialog::getOpenFileName(this);
    QPixmap pixMap;
    pixMap.load(filename);
    ui->label->setPixmap(pixMap);
 
    QBuffer buffer;
    QDataStream out(&buffer);
    buffer.open(QBuffer::ReadWrite);
    out<<pixMap;
    qDebug()<<buffer.size();
    int size = buffer.size();
    if(!shareMemory.create(size))
    {
        qDebug()<<tr("can't create memory segment");
        qDebug()<<shareMemory.error();
        return;
    }
    qDebug()<<shareMemory.size();
    shareMemory.lock();
    char *to = (char*)shareMemory.data();
    const char *from = (char*)buffer.data().data();
    memcpy(to,from,qMin(size,shareMemory.size()));//数据从该进程中拷贝到共享数据内存中
    shareMemory.unlock();//共享内层解锁
}

从共享内存中取数据的一方:

main.cpp
 
#include <QtGui/QApplication>
#include "widget.h"
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    
    return a.exec();
}
widget.h
 
#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include <QSharedMemory>
 
namespace Ui {
class Widget;
}
 
class Widget : public QWidget
{
    Q_OBJECT
    
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    
private slots:
    void on_pushButton_clicked();
 
private:
    Ui::Widget *ui;
    QSharedMemory shareMemory;
};
 
#endif // WIDGET_H
widget.cpp
 
#include "widget.h"
#include "ui_widget.h"
#include <QBuffer>
#include <QDebug>
 
 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    shareMemory.setKey("share");//设置标志一定要与共享内存的标志一样
    this->on_pushButton_clicked();
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::on_pushButton_clicked()
{
    if(!shareMemory.attach())//将shareMemory与该进程绑定使之可以访问shareMemory里的内容
    {
        qDebug()<<tr("can't attach share memory");
    }
    QBuffer buffer;
    QDataStream in(&buffer);
    QPixmap pixMap;
    shareMemory.lock();//给shareMemory枷锁
    qDebug()<<shareMemory.size();
    buffer.setData((char*)shareMemory.constData(),shareMemory.size());//将shareMemeory里的数据放到buffer里
    buffer.open(QBuffer::ReadWrite);
    in>>pixMap;
    shareMemory.unlock();//将shareMemory解锁
    shareMemory.detach();//将shareMemeory与该进程分离
    ui->label->setPixmap(pixMap);
}

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值