转自: http://www.cuteqt.com/blog/?p=1813
在我的这篇文章中使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.首先从http://qt.nokia.com的网站把QtSingleApplication的源代码qtsingleapplication-2.6_1-opensource.zip下载下来,然后解压缩。假设解压缩到路径:
E:/qtsingleapplication-2.6_1-opensource
2. 编写程序代码如下:
#include <QLabel>
#include <QWidget>
#include <QMessageBox>
#include <QApplication>
#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("<h2>test</h2>");
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使用的几种方法,大家可以根据自己的实际情况选择最适合自己的。
Powered by Zoundry Raven