Browsed by
Tag: qt

qt.qpa.xcb: could not connect to display :10.0

qt.qpa.xcb: could not connect to display :10.0

miniDNServer 启动 DNS 服务需要绑定标准 53 端口,在 Linux 系统下默认需要有 root 权限(或者 sudo )才能绑定 1024 以下的端口。一般情况下都能正常运行,但是在 Pi 系统中以 sudo 方式运行时,提示以下错误:

No protocol specified
qt.qpa.xcb: could not connect to display :10.0
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: xcb.

这个是 X11 auth 导致的问题。sudo 用户没有设置访问 x server 的权限,按以下步骤可以解决:

(1)当前正常用户执行以下命令,查看正常 cookie:

xauth list $DISPLAY

正常情况下会显示多条记录,如下所示:

raspberrypi/unix:10 MIT-MAGIC-COOKIE-1 4f8433752c1eac61313208cbf9050683
raspberrypi/unix:11 MIT-MAGIC-COOKIE-1 2c67fcb8cf523a837bedadcebad49958
raspberrypi/unix:0 MIT-MAGIC-COOKIE-1 0cd700917a92e9f330154efdd19b6acf

(2)将这些结果全部加入 sudo 的 xauth,如下所示:

sudo xauth add raspberrypi/unix:10 MIT-MAGIC-COOKIE-1 4f8433752c1eac61313208cbf9050683
sudo xauth add raspberrypi/unix:11 MIT-MAGIC-COOKIE-1 2c67fcb8cf523a837bedadcebad49958
sudo xauth add raspberrypi/unix:0 MIT-MAGIC-COOKIE-1 0cd700917a92e9f330154efdd19b6acf
Error: “此流的格式错误。”

Error: “此流的格式错误。”

最近在移植 miniSIPPhone 到 Linux 系统时,遇到一个奇怪的错误:播放 wav 语音文件时提示“此流的格式错误”,无论是采用 QSound 还是 QMediaPlayer 播放 wav 文件都出现了这个错误。按照我们一贯以来的要求,miniSIPServer 和 miniSIPPhone 的语音文件都采用了同样的格式:

CCITT A-Law, 8KHZ, 8Bit, 7KB/sec, 单通道

换用 VLC 播放没有任何问题,在 Windows 系统上播放也没有任何问题。考虑到 Qt 在 Linux 系统上实际是调用 GStreamer 的 plugins 来解码和播放各种语音格式,而我们的录制格式是如此的普通和平平无奇,实在想不通为什么会出现格式错误。

遍历了各种可能原因后忽然想到,或许 GStreamer 默认不支持 A-Law?这个格式在通信领域用得比较多,而一般语音播放、音乐等软件可能不太会关注这种格式。将语音文件格式转换成以下格式:

CCITT PCM, 8KHZ, 8Bit, 7KB/sec, 单通道

然后果然成功了,miniSIPPhone 在 Linux 平台也可以正常播放各种提示音。

could not find a Qt installation of ”

could not find a Qt installation of ”

最近重新搭建了一套 Debian 系统的开发环境,使用 qmake 编译 pro 文件时,提示了标题中的错误。检查qmake 文件,发现以下信息:

 /usr/bin/qmake -> qtchooser

这是因为系统提供了两套 Qt 开发环境,比如 Qt6 和 Qt5 等,因此需要指定默认采用哪一套。网络上的解决方案大多数比较粗暴,手工修改 /usr/bin/qmake 的文件链接,链接到真实的 qmake 文件即可。

但实际上系统提供了更简单的方式,比如我们默认采用 Qt5 的开发环境,则使用以下命令:

sudo apt install qt5-default
装机 – Ubuntu16.04

装机 – Ubuntu16.04

老婆公司有个让人惊讶的规定:员工笔记本三年后归自己个人所有,公司重新配新电脑! 这是多么让人热爱的公司!老婆工作这几年,家里多了几台笔记本,一水的ThinkPad。上周又过了三年,拿回一台T430。以前拿回电脑时,会恢复到Thinkpad出厂时安装的window系统,这次这台T430居然只是低格了,没有系统?!

当然可以从网上扒一个windows恢复盘下来重装,不过考虑到家里已经有几台windows的笔记本和台式机,实在没有必要再增加一台,因此这次打算装Linux系统试试。

选择发行版本

“Linux发行版本”之争在程序员迷之争论中绝对可以位列前三位!好在是给自己的笔记本选发行版,因此有幸避免了与别人的争论,只要考虑自己的需求就好了。我的基本原则其实很简单:

(1)发行版要有强大的、历史悠久的社区。

(2)或者,有商业背景企业发布的版本。

以上两点只确保一个问题:若干年后,依然能活着并得到强有力的支持。绝大多数妖艳的Linux发行版本,比如Arch等,基本不用考虑了。符合要求的版本大致也就是:Debian、CentOS、Ubuntu等寥寥数种而已。

CentOS的软件实在太老旧了点,有时候不得不自己去编译各类软件,与其这样,还不如用Arch或者Gentoo等版本来得直接。公司做项目时基本都是采用Debian系统做服务器,很满意,但是Debian桌面系统就差强人意。不知道是Debian的问题,还是KDE的问题,使用时总有各种烦人的小毛病,比如鼠标问题等。

因此这次就选择了Ubuntu 16.04 (Unity7),谁会做死去选择Ubuntu的非LTS版本呢?

安装软件

安装Ubuntu系统实在没什么可以说的,下载iso文件,录制u盘,直接安装即可,比装windows还简单,过程枯燥乏味。下面只是记录一些安装应用软件方面需要注意的地方。

安装virtualBox与Windows环境下稍有不同,扩展功能包也收录在软件中心,因此实际执行命令一起安装:

sudo apt-get install virtualbox virtualbox-ext-pack

将其他计算机中的vbox客机导出到新计算机中,U盘必须采用exFat格式才能支持超过4G大小的文件,ubuntu默认没提供对该格式的支持,因此也需要单独安装:

sudo apt-get install exfat-utils

qt开发工具集升级到qt5了,采用以下命令安装:

sudo apt-get install qt5-default
掉坑里了

掉坑里了

Qt无疑是个非常好的framework,我们一直用TA。虽然不敢说已经是行家里手,不过好歹也开发这么久程序了,渐渐地有些自负起来,因此掉坑里了。

坑来自Qt最经典的设计:signal-slot。我以前的理解这是异步的,常用于模块间解耦。在windows平台,这个理解似乎没错,signal-slot底层依赖window的message机制。而在linux平台,其实现方式默认仍然是callback机制。

callback机制在多线程编程里最容易出问题的就是“锁”。这次掉坑里,就是在slot中应用“锁”时不小心,导致了死锁。

这次竟然忘了这点! :-(

qt network中的一点问题

qt network中的一点问题

在一个小应用中使用了qt的network模块,调用网站的一个接口(HTTP GET方式),获得相应的结果。操作非常简单,可是却出现了问题。

首先是在windows上,运行程序后,提示无法定位libeay32.dll。这个是openSSL的动态链接库,不明白为什么qt4.8.5(windows)默认链接了这个库。查看文档,貌似缺省情况下是不编译进SSL功能的,而且我们用的包并不是自己编译的,是直接从qt网站下载安装的。解决方法也简单,无非就是安装openssl的库,copy相应的dll到exe文件同一目录下即可。

接着又出现了问题,调用HTTP后,服务器返回“406 NOT acceptable”。直接将链接放在浏览器中执行又没有任何问题。检查server上的log,发现apache启动了ModSecurity模块,该模块检查了User-Agent头,如果太简单则认为是假请求(spam请求?),拒绝该HTTP请求。

用wireshark抓了一下包,发现QNetworkRequest默认的User-Agent的确非常简单:

User-Agent: Mozilla/5.0

解决方式同样简单,我们强行修改为稍微复杂一点即可,例如:

QNetworkRequest netReq;
netReq.setUrl(destUrl);
netReq.setRawHeader("User-Agent","Mozilla/5.0 (X11; Linux x86_64)");

这样就可以绕开apache模块的检查。

qt编译中抑制特定告警信息

qt编译中抑制特定告警信息

在编译某些代码时,我们希望抑制掉一些VC的编译告警,例如C4244(丢失精度告警)。我们可以直接修改mkspecs目录下对应的配置文件,但这样做会影响到所有工程,而我们实际上只希望对某些特定的工程关闭该告警。

可以直接修改pro文件,加入以下内容即可:

QMAKE_CFLAGS += /wd4244

如果是cpp文件,则指定以下参数即可:

QMAKE_CXXFLAGS += /wd4244
Phonon程序无法播放语音文件的问题

Phonon程序无法播放语音文件的问题

问题基本情况如下:我们开发并发布了一个软终端产品,当然其中采用QT以及Phonon模块。在我们的开发环境中,一切都很美好,能正常地播放音乐。可是安装到客户的计算机上,出现问题了,无法播放提示语音(wav文件录制)。

这个问题的实质是我们没有将Phonon的插件一同打包进安装文件。Phonon实质上只是个前端封装模块,具体工作有赖于后台的解码器。在windows系统中,Phonon缺省采用DirectX作为后台解码器部分,具体实现为一个plugin。如果不安装这个plugin,则phonon无法正常播放语音文件。

假设QT安装在d:\qt\4.8.4目录下,则上述plugin可以在以下目录中找到:D:\Qt\4.8.4\plugins\phonon_backend\phonon_ds94.dll。

注意,不是简单地将这个文件拷贝到程序目录下即可,而是要拷贝到程序目录的phonon_backend子目录下。例如,我们的程序安装在d:\minisipphone目录,则上述dll应当拷贝为:d:\minisipphone\phonon_backend\phonon_ds94.dll。

另外需要注意的是,不同版本的QT要采用各自版本的phonon_ds94.dll,例如qt 4.6.2的程序就不能采用qt 4.8.4的phonon_ds94.dll,否则还是会出现放音错误。

QT程序自动重启

QT程序自动重启

一行代码就可以了:

// restart application
QProcess::startDetached(qApp->applicationFilePath(), QStringList());
QT程序与gprof

QT程序与gprof

gprof能分析出函数的调用关系以及占用时间,对分析程序性能瓶颈很有帮助。

在采用QT开发时,如果程序分成若干个库,那么仅仅在编译时加入-pg选项是不能产生gmon.out文件,还必须在链接选项中也加入-pg才可以。在pro文件中做如下设置即可:

QMAKE_CXXFLAGS += -pg
QMAKE_LFLAGS += -pg

让人比较郁闷的是,gprof不支持动态链接库和Multi-Thread程序。这实在是非常大的局限。