Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1636835
  • 博文数量: 584
  • 博客积分: 13857
  • 博客等级: 上将
  • 技术积分: 11883
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-16 09:34

分类: WINDOWS

2011-07-18 12:08:24

在我的这篇文章中使Qt程序只运行一个实例,通过QSharedMemory来实现进程间通讯,使用这种方式来是Qt程序只运行一个实例。有一天测试部的MM告诉我,她在测试的时候,程序crash掉了,再次运行程序,程序不能继续运行。

程序不能运行,显然是共享内存没有释放引起的,但是程序crash后为什么共享内存不能释放呢?于是打开Qt助手看到QSharedMemory是这样解释的:

Unix: QSharedMemory "owns" the shared memory segment. When the last thread or process that has an instance of QSharedMemory attached to a particular shared memory segment detaches from the segment by destroying its instance of QSharedMemory, the Unix kernel release the shared memory segment. But if that last thread or process crashes without running the QSharedMemory destructor, the shared memory segment survives the crash.

怎么可以这样?555…看来Nokia提供的QtSingleApplicationsolution的方法还是蛮好的。真是杯具丫,只好换 QtSingleApplication,下面就介绍一下我把QSingleApplication整合到自己的应用程序中去的方法一:

1.首先从的网站把QtSingleApplication的源代码qtsingleapplication-2.6_1-opensource.zip下载下来,然后解压缩。假设解压缩到路径:

E:/qtsingleapplication-2.6_1-opensource

2. 编写程序代码如下:

 

#include
#include
#include
#include
#include "E:/qtsingleapplication-2.6_1-opensource/src/QtSingleApplication"

int main(int argc,char* argv[])
{
    QtSingleApplication app(argc,argv);
    if (app.isRunning())
    {
        QMessageBox::information(0, "test",
                    "An instance has already been running.");
        return 0;
    }
    QLabel label("

test

");
    label.show();
    return app.exec();
}

3.编译

qmake –project

qmake

nmake

链接器报告我们链接错误,链接不到QtSingleApplication的构造函数和isRunning()函数。错误很明显,编译的时候找到了QtSingleApplication的定义,但是链接器链接不到二进制符号。

4.打开刚刚生成的pro文件,加入

include(E:/qtsingleapplication-2.6_1-opensource/src/qtsingleapplication.pri)

然后qmake&nmake

这样我们的单实例程序就可以运行了,并且在linux下,当程序crash掉的时候不会存在类似sharedmemory不释放的问题。

注意:QtSingleApplication依赖于QtNetWork模块,因为其进程间通讯是通过socket来实现的,所以我们在发布程序的时候不要忘记带上QtNetWork4.dll

上面的方法虽然可以编译生成单实例程序,但是并不是我想要的最终的解决方案。因为不可能要求我的同事都下载下 QtSingleApplication来,然后照着上面的说明来做,更何况大家放置QtSingleApplication的路径也不可能一样(当然可 以通过make&make install把QtSingleApplication安装到Qt的路径下),总是觉得这样做会给大家带来麻烦,索性直接把 QtSingleApplication的代码编译到我的工程里去算了,QtSingleApplication随着工程一起就不会存在上面描述的问题 了。下面介绍方法二

介绍一下把QtSingleApplication代码编译到程序中的方法:

1. 在当前程序路径下新建文件夹qtsingleapplication和qtlockedfile。

将qtlocalpeer.cpp、qtlocalpeer.h、qtsingleapplication.cpp、 qtsingleapplication.h、qtsinglecoreapplication.cpp、 qtsinglecoreapplication.h拷贝到qtsingleapplication文件夹下;

将qtlockedfile.cpp、qtlockedfile.h、qtlockedfile_unix.cpp、qtlockedfile_win.cpp拷贝到qtlockedfile文件夹下

2. 修改pro文件:

win32 {

SOURCES += qtlockedfile/qtlockedfile_win.cpp

}

unix {

SOURCES +=qtlockedfile/qtlockedfile_unix.cpp

}

SOURCES += test.cpp /

qtsingleapplication/qtlocalpeer.cpp /

qtsingleapplication/qtsingleapplication.cpp /

qtsingleapplication/qtsinglecoreapplication.cpp /

qtlockedfile/qtlockedfile.cpp

HEADERS += qtsingleapplication/qtlocalpeer.h /

qtsingleapplication/qtsingleapplication.h /

qtsingleapplication/qtsinglecoreapplication.h /

qtlockedfile/qtlockedfile.h

修改刚才编写的cpp文件,将原来的include文件的路径改为相对路径。

#include "qtsingleapplication/qtsingleapplication.h"

3. 这时,运行一下qmake、nmake,出现了一大堆链接错误,仔细一看,原来是QtNetWork中的函数,昏倒,刚才还在上面提醒大家要在发布的时候 包含QtNetwork4.dll,就在这里忘记包含了QtNetwork。打开pro文件,加上一句QT +=network,然后qmake、nmake恭喜,现在没有问题了。运行一下,确实是我们需要的结果。

或许你也会嫌这种方法麻烦,每次都需要改pro文件,还要包含这么多头文件和源文件,当然,我们还可以把qtsingleapplication编 译成一个lib文件,在使用的时候,只需要include头文件,链接的时候把lib添加上就可以了。这个方法和方法二差不多,不同的地方在于编译静态库 要在pro中使用下面参数:

TEMPLATE = lib

CONFIG +=static

相信你一定能编译出并且使用lib文件。

上面提供了使用QtSingleApplication使用的几种方法,大家可以根据自己的实际情况选择最适合自己的。

对于像我这种新的不能再新的新手来说,要想编写一个只运行单一实例的qt程序,用QtSingleApplication就最好不过了。

首先,去官网下载LGPL版本的源代码,/products/appdev/add-on-products/catalog/4/Utilities/qtsingleapplication/

然后解压缩,打开Qt Command prompt,cd到解压缩的文件夹。输入configure.bat -library,然后输入yes接受协议,然后输入

qmake

mingw32-make

将解压缩文件夹里面的src/qtsingleapplication.h 复制到 qt的include文件夹里面,例如:D:/Qt/2009.04/qt/include/QtSolutions/qtsingleapplication.h

———-沮丧的分割线———-

新建一个Qt Gui项目,参考下面的代码来修改main函

01 #include 《QtSolution/qtsingleapplication.h》
02 #include 《QMainWindow》
03   
04 int main(int argc, char *argv[])
05 {
06 QtSingleApplication app(argc,argv);
07   
08 if(app.isRunning())//app.isRunning()判断是否已经有一个实例正在运行了。
09 {
10 return 0;
11 }
12   
13 QMainWindow w;
14 w.show();
15 return app.exec();
16 }

编译之前还得修改.pro文件,添加LIBS参数。

1 LIBS += -LD:/Qt/2010.02.1/qt/bin -lQtSolutions_SingleApplication-2.6d

PS: LIBS的写法:LIBS += -L文件夹 -l链接库文件(不要后缀)

阅读(2502) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~