c语言sscanf函数的用法是什么
280
2022-11-29
QT开发GIF截屏工具的问题记录
项目地址:log 重定向问题。
描述:在QML中的log print成功输出所有信息,CPP中的打印不能显示文件名,行号,函数名
看了帮助文档中的例子 QtMessageHandler qInstallMessageHandler(QtMessageHandler handler) 安装我们自己的handler后可以重定向
#include
我使用在自己的项目中,源代码如下
...int main(){//...qInstallMessageHandler( LogBase );//...return 0;}
结果log 重定向,QML成功打印所有信息,CPP中的打印不能显示文件名,行号,函数名
[Debug ((null), 0, (null))] LogInit finished.[Warning (qrc:/main.qml, 72, (null))] qrc:/main.qml:72:9: QML Button: Cannot anchor to an item that isn't a parent or sibling. [Debug (qrc:/main.qml, 30, onPressed)] onPressed: (613.9609375, 507.06640625)
在查看源码后,发现QMessageLogContext有两种构造方式。
class QMessageLogContext{ Q_DISABLE_COPY(QMessageLogContext)public: Q_DECL_CONSTEXPR QMessageLogContext() : version(2), line(0), file(Q_NULLPTR), function(Q_NULLPTR), category(Q_NULLPTR) {} Q_DECL_CONSTEXPR QMessageLogContext(const char *fileName, int lineNumber, const char *functionName, const char *categoryName) : version(2), line(lineNumber), file(fileName), function(functionName), category(categoryName)
在我们的工程中,CPP类下的QMessageLogContext构造使用了第一种方式,QML下的的QMessageLogContext构造使用了第二种方式。我想,这和应用程序的启动相关,本工程使用QQmlApplicationEngine启动。 我们可以通过修改message handler函数来保证文件名,行号,函数名的输出:
const QMessageLogContext &context = QMessageLogContext( __FILE__, __LINE__, __FUNCTION__, NULL ), const QString &msg = QString("") ) {
Qt Quick设置icon
在pro文件中加上:
macx{ message("compile for mac os x") ICON = Images/logo.icns}
重新生成Makeifle,再make。
双击mac程序,程序在移动文件时提示没有权限。
双击app启动程序,我一开始猜想是Finder进程启动app进程。使用pstree可以查看相关的进程派生关系。可以使用brew安装pstree。 查询Finder相关的分支:
➜ Images git:(master) ✗ ps aux |grep Finderweiyang 284 0.0 0.5 4751940 45756 ?? R 14Jul18 9:12.45 /System/Library/CoreServices/Finder.app/Contents/MacOS/Finderweiyang 27974 0.0 0.0 4267752 576 s002 R+ 9:07AM 0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn Finder➜ Images git:(master) ✗ pstree -p 284-+= 00001 root /sbin/launchd \--= 00284 weiyang /System/Library/CoreServices/Finder.app/Contents/MacOS/Find
用类似的方法,查询双击Gifer.app后的进程派生关系。
➜ Images git:(master) ✗ ps aux |grep Giferweiyang 28107 0.2 0.6 4474736 46468 ?? S 9:08AM 0:01.01 /Users/weiyang/pro/Gifer/Gifer.app/Contents/MacOS/Giferweiyang 28129 0.0 0.0 4267752 532 s002 R+ 9:09AM 0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn Gifer➜ Images git:(master) ✗ pstree -p 28107-+= 00001 root /sbin/launchd \--= 28107 weiyang /Users/weiyang/pro/Gifer/Gifer.app/Contents/MacOS/Gifer
原来,是launchd启动app的。 那么命令行启动的进程派生又是怎么样子的呢?
➜ Images git:(master) ✗ ps aux |grep Giferweiyang 28395 0.0 0.0 4267752 640 s002 R+ 9:16AM 0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn Giferweiyang 28342 0.0 0.6 4476844 46860 s001 S+ 9:15AM 0:00.70 ./Gifer➜ Images git:(master) ✗ pstree -p 28342-+= 00001 root /sbin/launchd \-+= 17185 weiyang /Applications/iTerm.app/Contents/MacOS/iTerm2 \-+= 17249 weiyang /Applications/iTerm.app/Contents/MacOS/iTerm2 --server lo \-+= 17250 root login -fp weiyang \-+= 17251 weiyang -zsh \--= 28342 weiyang ./Gifer
命令行启动的进程是由终端进程启动的。
在源码中,我使用了QDir::current().absolutePath()定位程序的路径,但他返回的是/。进一步查看该函数的解释
[static] QDir QDir::current() Returns the application’s current directory. The directory is constructed using the absolute path of the current directory
再看看QCoreApplication::applicationDirPath()的解释
[static] QString QCoreApplication::applicationDirPath() Returns the directory that contains the application executable. For example, if you have installed Qt in the C:\Qt directory, and you run the regexp example, this function will return “C:/Qt/examples/tools/regexp”.
在程序启动起来后QDir QDir::current()返回的application’s current directory是不确定的。 如果是双击app启动,返回值是/;如果是命令行启动,返回值是可执行文件的路径,也就和QCoreApplication::applicationDirPath()一样了。 后者是我们需要的函数。
使用system运行命令的问题
假设我使用system运行这样一条命令: ffmpeg -threads 1 -y -r 70 -i /Users/weiyang/pro/Gifer/Gifer.app/Contents/MacOS/Pictures/out%d.png -final_delay 300 /Users/weiyang/pro/Gifer/Gifer.app/Contents/MacOS/Pictures/output.gif 再这样判断:
; if( -1 == ret || 127 == ret ) { tmp = cmdStr + strerror(errno); qWarning() << tmp; QMessageBox::information( this, tr("Combine Gif Failed"), tmp, QMessageBox::Ok ); return false;
判断依据来自于mac上的帮助文档
RETURN VALUES The system() function returns the exit status of the shell as returned by waitpid(2), or -1 if an error occurred when invoking fork(2) or waitpid(2). A return value of 127 means the execution of the shell failed.
system的工作大致是这样的: 父进程fork子进程 父进程等待子进程 在子进程中执行字符串所表述的命令 返回执行结果。
我将源码改成:
system( cmdStr.toStdString().c_str() ); // create sub qCritical("system error!"); } else { qDebug("ret is not -1, exit ret value = [0x%x]", ret); //0x7f00 // call shell script and finish successfully. if (WIFEXITED(ret)) // WIFEXITED is a macro { if (0 == WEXITSTATUS(ret)) // return value of shell script run. { qDebug("run shell script successfully."); } // 0x7f = 127 else { qCritical("run shell script fail, script exit code: %d, reason: %s", WEXITSTATUS(ret), strerror(errno)); } } else { qCritical("exit ret = [%d]", WEXITSTATUS(ret)); } }
当我在shell终端中命令行方式启动后,没有问题。但如果是双击Gifer.app就会是这样的结果:
[Debug (windowgrabber.cpp, 159, bool WindowGrabber::combineImages())] ret is not -1, exit ret value = [0x7f00][Critical (windowgrabber.cpp, 171, bool WindowGrabber::combineImages())] run shell script fail, script exit code: 127, reason: No such file or
一样的命令,结果却是不同的。 我找到了ffmpeg的具体位置,然后在system的命令中也给出ffmpeg的绝对路径,问题就不存在了。也就是说,在双击启动app的方式下,系统找不到ffmpeg。 在双击启动app的方式下,PATH的值是
/usr/bin:/bin:/usr/sbin:/sbin
此结果在代码中添加system("echo $PATH > ~/code/txt");可以检测出来。 这和我在~/.bashrc下的设置是不一样的。 新的PATH值刚好对应
/usr/include/paths.h67:#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"/usr/libexec/security-checksystem12:export PATH=/usr/bin:/bin:/usr/sbin:/sbin/usr/local/Homebrew/bin/brew71: PATH="/usr/bin:/bin:/usr/sbin:/sbin"
system的源码为:
int system(const char * cmdstring){ pid_t pid; int status; if( cmdstring == NULL ) { return 1; } if( (pid = fork()) < 0 ) { status = -1; } else if( pid == 0 ) { // execl create new process to replace old process execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); // if above statement execute successfully, the following function would not work. _exit(127); } else { while( waitpid(pid, &status, 0) < 0 ) { if( errno != EINTR ) { status = -1; break; } } } return
execlp搜索目录默认值是paths.h中的_PATH_DEFPATH。也就是前面提到过的/usr/bin:/bin:/usr/sbin:/sbin
For execlp() and execvp(), search path is the path specified in the environment by PATH variable. If this variable is not specified, the default path is set according to the _PATH_DEFPATH definition in
故,在/usr/bin/下建立一个软连接即可。
➜ ~ sudo ln -s
怎样使得dmg安装包自带Application文件夹
之前打包都是使用QT的打包功能,macdeployqt或windeployqt,但是生成的dmg有一个缺点,他没有Application文件夹图标生成。每次都需要拖动到Finder中的Application。 我在看到了一位大神Linus Unnebäck 的回答,他的方案简单易懂。
brew install nodenpm install
创建spec.json
{ "title": "Gifer Installer", "icon": "Images/logo.icns", "background": "Images/back.png", "icon-size": 80, "contents": [ { "x": 100, "y": 120, "type": "file", "path": "Gifer.app"}, { "x": 400, "y": 120, "type": "link", "path": "/Applications"} ], "window": { "size": { "width": 500, "height": 300} }}
生成dmg: appdmg spec.json Gifer.dmg 效果:
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~