您的位置:首页 > 编程语言 > C语言/C++

C++学习之路(8)---Qt学习—qt共享内存的使用

2017-08-19 21:21 489 查看
Qt提供了QSharedMemory类来访问共享内存,实现共享内存的操作。

一、QSharedMemory类常用的操作
1、[b]QSharedMemory类对象的创建[/b]
利用QSharedMemory类创建实例对象时,必须为该共享内存指定关键字(即为该共享内存起一个名字)。只有当共享内存被设置了关键字之后,才可以执行创建create()、关联attach()等操作。为共享内存指定关键字有两种方法:

① 通过构造函数QSharedMemory::QSharedMemory (
const QString & key, QObject * parent =0
)为实例对象传入关键字;

例如:

SharedMemory* sharememory;


sharememory = newQSharedMemory("QSharedMemoryExample");

② 通过构造函数QSharedMemory::QSharedMemory (QObject * parent =
0 )
构造实例对象,之后调用setKey()函数为该实例对象设置关键字。
例如:
QSharedMemory* sharememory;
sharememory = new QSharedMemory();
sharememory->setKey("QSharedMemoryExample ");

2、创建共享内存

bool QSharedMemory::create ( int size, AccessMode mode =ReadWrite
)

为QSharedMemory类实例对象创建一个空间大小为size的共享内存,该内存空间默认的访问方式为可读可写。共享内存创建成功返回true,否则返回false。QSharedMemory类定义一个枚举类变量AccessMode,指定了两种共享内存的访问方式:

QSharedMemory::ReadOnly   只读方式访问共享内存
QSharedMemory::ReadWrite  读写方式访问共享内存
 

3、关联共享内存

bool QSharedMemory::attach ( AccessMode mode =ReadWrite
)

将以关键字key命名的共享内存和当前程序进行关联,共享内存默认的访问方式为可读可写。如果程序和共享内存关联成功,返回true,否则返回false。

 

4、分离共享内存

bool QSharedMemory::detach ()

解除共享内存和程序的关联,即调用该函数后,程序不可以再访问共享内存。如果该共享内存被多个程序实例所关联,当最后一个程序实例和共享内存解除关联后,该共享内存将由操作系统自动释放掉。分离操作成功,返回true。如果返回false,通常意味着该共享内存和程序分离失败,或者其他程序当前正在访问该共享内存,分离操作执行失败。

5、判断共享内存的关联状态

bool QSharedMemory::isAttached ()const

该函数用来判断程序(调用该函数的程序)是否和共享内存进行关联,是返回true,否返回false。

6、设置/获取共享内存的关键字

QString QSharedMemory::key ()const                                
//获取共享内存关键字

Qt应用程序通过关键字来辨识共享内存。key ()函数用来获取共享内存的关键字,如果没有指定实例对象的关键字,或者共享内存的关键字是由nativeKey ()函数指定的话,则返回空。 

void QSharedMemory::setKey (const QString & key )       
//设定共享内存关键字

setKey ()函数用来为共享内存段设定关键字(为共享内存命名),如果参数key的值和构造函数或者之前指定的关键字相同的话,则该函数将不做任何操作,直接返回。
 

7、锁定/解锁共享内存

bool QSharedMemory::lock ()                   
//锁定共享内存

如果共享内存资源当前处于释放状态,进程调用该函数将共享内存中的资源锁定,并返回true。其他进程将不能访问该共享内存。如果共享内存被其他进程占用时,则该函数会一直处于阻塞状态,直到其他进程使用完毕,释放共享内存资源。

bool QSharedMemory::unlock ()        
//解锁共享内存

如果共享内存资源被当前进程所占有,调用该函数将解锁该共享资源,并返回true。如果当前进程没有占用该资源,或者共享内存被其他进程访问,则不做任何操作并返回false。

 

为了保证共享内存中数据的完整性,当一个进程在读写共享内存的时候,其他进程不允许对该共享区域进行访问。QSharedMemory类提供了lock()函数和unlock()函数来实现这一共享内存访问机制。某一程序对共享内存进行读写操作之前,需要调用lock()函数锁定该共享内存,之后独享共享内存中的数据,并对数据进行读写等操作。共享内存访问完毕,调用unlock()函数,释放共享内存的使用权限。

8、错误原因

SharedMemoryError QSharedMemory::error ()const 

当共享内存出错时,调用该函数显示相应的错误代码。

QString QSharedMemory::errorString ()const

当共享内存出错时,调用该函数,以文本形式显示错误原因。

9、获取共享内存的地址

const void *QSharedMemory::constData ()const

void * QSharedMemory::data ()

const void *QSharedMemory::data ()const         
//重载函数

程序关联共享内存的前提下,调用该函数返回共享内存中数据的起始地址。如果没有关联共享内存,则返回0。
 
10、获取共享内存的大小

int QSharedMemory::size ()const

调用该函数将返回程序所关联的共享内存的大小(字节)。如果没有关联的共享内存,则返回0。
 
二、示例代码
① main.cpp源文件

#include <QtGui/QApplication>

#include "dialog.h"

#include <QTextCodec>


int main(int argc, char *argv[])

{

QApplication application(argc, argv);

//Qt国际化显示

QTextCodec::setCodecForTr(QTextCodec::codecForName("GB18030"));

QTextCodec::setCodecForLocale(QTextCodec::codecForName("GB18030"));

QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB18030"));


Dialog dialog;

dialog.show();


return application.exec();

}



② dialog.h头文件

#ifndef DIALOG_H

#define DIALOG_H


#include <QDialog>


//调试用头文件

#include <QDebug>

#include <QMessageBox>


#include <QFileDialog>

#include <QDir>

#include <QPixmap>

#include <QImage>

#include <QDataStream>

#include <QBuffer>

#include <QSharedMemory>


namespace Ui {

class Dialog;

}


class Dialog : public QDialog

{

Q_OBJECT


public:

explicit Dialog(QWidget *parent = 0);

~Dialog();

public slots:

void loadFromFile();        //载入图片按钮 响应函数

void loadFromMemory();      //显示图片按钮 响应函数


private:

Ui::Dialog *ui;

QSharedMemory *sharememory; //定义共享内存实例指针

bool first_flag;            //判断是否是首次加载文件

};


#endif // DIALOG_H



③ dialog.cpp源文件

#include "dialog.h"

#include "ui_dialog.h"


#define DEBUG           //调试开关



Dialog::Dialog(QWidget *parent) :

QDialog(parent),

ui(new Ui::Dialog)

{

ui->setupUi(this);

QObject::connect(ui->PBtn_Load,SIGNAL(clicked()),this,SLOT(loadFromFile()));

QObject::connect(ui->PBtn_Display,SIGNAL(clicked()),this,SLOT(loadFromMemory()));


sharememory = new QSharedMemory();              //构造实例对象

sharememory->setKey("QSharedMemoryExample");    //为实例对象指定关键字(给共享内存命名)

first_flag = true;

}


Dialog::~Dialog()

{

delete ui;

}


//载入图片按钮响应函数

void Dialog::loadFromFile()

{

if(sharememory->isAttached())       //检测程序当前是否关联共享内存

sharememory->detach();          //解除关联

ui->Label_Display->setText(tr("请选择一张图片"));


QString filename = QFileDialog::getOpenFileName(

this,"打开",QString(),tr("Image (*.png *.xpm *.jpg)"));

QImage image;

if(!image.load(filename))           //将打开的图片文件和QImage实例关联

{

ui->Label_Display->setText(tr("您选择的不是图片文件,请重新选择"));

return;

}

ui->Label_Display->setPixmap(QPixmap::fromImage(image));


QBuffer buffer;

buffer.open(QBuffer::ReadWrite);    //构建并打开数据缓冲区,访问方式为读写

#ifdef DEBUG

qDebug()<<"新建缓冲区的大小为:"<<buffer.size();  //测试缓冲区大小(一般为0)

#endif


QDataStream in(&buffer);            //建立数据流对象,并和缓冲区相关联

in << image;                        //向缓冲区写入数据

int size = buffer.size();           //获取写入数据的大小(图片的大小)


#ifdef DEBUG                             //调试部分

qDebug()<<"缓冲区的大小为:"<<size;

qDebug()<<sharememory->key();

qDebug()<<sharememory->nativeKey();

//    sharememory->setKey("共享内存");   //修改共享内存的关键字,将无法访问共享内存

qDebug()<<sharememory->key();

qDebug()<<sharememory->nativeKey();

qDebug()<<sharememory->error();

qDebug()<<sharememory->errorString();

#endif


if(true == first_flag)

{

if (!sharememory->create(size)) //创建共享内存,大小为size

{

ui->Label_Display->setText(tr("无法创建共享内存段"));

        qDebug()<<sharememory->errorString();

    return;

}

first_flag = false;

qDebug()<<sharememory->size();  //显示共享内存的大小

}

//对共享内存进行读写操作

sharememory->lock();        //锁定共享内存

char *to = (char*)sharememory->data();      //获取共享内存中的地址

const char *from = buffer.data().data();    //获取有效数据在缓冲区中的地址

memcpy(to, from, qMin(sharememory->size(), size));  //将缓冲区中的数据复制到共享内存

sharememory->unlock();      //释放共享内存

}


//显示图片按钮响应函数

void Dialog::loadFromMemory()

{

if (!sharememory->attach())     //关联共享内存

{

ui->Label_Display->setText("无法关联共享内存");

 return;

}


 QBuffer buffer;                //构建缓冲区

QDataStream out(&buffer);      //建立数据流对象,并和缓冲区关联

 QImage image;

 //对共享内存进行读写操作

sharememory->lock();           //锁定共享内存


//初始化缓冲区中的数据,setData函数用来初始化缓冲区。

//该函数如果在open()函数之后被调用,则不起任何作用。

//buffer.open(QBuffer::ReadOnly);  //解除注释,则setData函数不起作用,无法加载内存中数据

buffer.setData((char*)sharememory->constData(), sharememory->size());

buffer.open(QBuffer::ReadOnly);    //只读方式打开缓冲区

out >> image;                      //将缓冲区的数据写入QImage对象


sharememory->unlock();         //释放共享内存


sharememory->detach();         //解除程序和共享内存的关联

 ui->Label_Display->setPixmap(QPixmap::fromImage(image));   //显示图片

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: