如何在Qt程序中嵌入一个二进制可执行文件(在运行时执行)?

8
我正在使用Qt编写一个跨平台的C++程序,并希望将多个二进制可执行文件打包/嵌入到程序中。该程序应能够在运行时执行这些二进制文件。
我认为,我需要使用QResource和QProcess,使用start()和“:/…”符号,但我似乎无法让进程运行起来。我是否漏掉了什么?它应该像这样工作吗?二进制文件需要被设置为可执行文件吗?
背景:我正在编写一个使用Git的工具,我不想要求最终用户手动安装Git。
(顺便说一下,我是在Mac OS X上尝试的。)
更新:
我正在使用以下代码(C ++,Qt在Mac OS X上):
QString program = ":/git";
QStringList arguments;
arguments << "help" << "commit";
myProcess->start(program, arguments);

Git可执行文件位于项目路径中,我的resources.qrc引用方式如下:
<qresource prefix="/">
    <file>git</file>
</qresource>

我没有收到错误信息,但程序并未执行。当我将 program 设置为不存在的文件时,行为相同。将 ":/git" 替换为 git 的绝对路径可以完美解决问题。

请提供源代码,特别是您提到使用QResource和QProcess的部分。 - Wildcat
我已经更新了问题,并附上了我使用的代码。 - jan
4个回答

11

无法直接从资源中执行程序。

如果您有一个在资源中的程序,并且想要执行它,您首先需要将其读出到文件中,将文件设置为可执行文件,然后再执行它。

另外,当您说没有收到错误消息时,这可能意味着您没有正确地检查错误。


谢谢Rohan。"没有出现错误"只是懒惰的说法,实际上是“它默默失败了”。我猜如果我仔细检查,我会得到一个错误 :) - jan
针对Windows系统:https://www.blackhat.com/presentations/bh-usa-07/Harbour/Whitepaper/bh-usa-07-harbour-WP.pdf - Dmitry Sazonov

5
几年过去了,但问题仍然相关。当我想要嵌入rclone时,我遇到了同样的问题。
.pro文件中添加:
# From https://dev59.com/Qm865IYBdhLWcg3wHKte#37561981
defineReplace(copyToDir) {
    files = $$1
    DIR = $$2
    LINK =

    for(FILE, files) {
        LINK += $$QMAKE_COPY $$shell_path($$FILE) $$shell_path($$DIR) $$escape_expand(\\n\\t)
    }
    return($$LINK)
}

defineReplace(copyToBuilddir) {
    return($$copyToDir($$1, $$OUT_PWD))
}

# Copy the binary files dependent on the system architecture
win32 {
    message("Windows")
    QMAKE_POST_LINK += $$copyToBuilddir($$PWD/rclone/windows/rclone.exe)
}else: unix:!macx {
    message("Linux")
    QMAKE_POST_LINK += $$copyToBuilddir($$PWD/rclone/linux/rclone)
}else: macx: {
    # Here we want to place the binaries inside the application bundle, so the 
    # QMAKE_POST_LINK approach will not work because it places them in the same
    # directory as the bundle and not inside it. Instead, use QMAKE_BUNDLE_DATA.
    message("macOS")
    MediaFiles.files += $$PWD/rclone/macOS/rclone
    MediaFiles.path = Contents/MacOS
    QMAKE_BUNDLE_DATA += MediaFiles
}

注意每个平台都有细微差别,但总体上方法相同。 qmake将把这些文件复制到目标目录中,只需通过调用本地相对目录的进程调用即可访问它们。
在下面的代码中,我从QML调用可执行文件,在C++中也非常类似:
var rcloneCommand
if (Qt.platform.os === "windows") {
    console.log("Windows")
    rcloneCommand = "rclone.exe"
} else {
    console.log("OSX/Linux")
    rcloneCommand = "./rclone"
}
qProcess.start(rcloneCommand, ["--config", "rclone.conf", "-v", "copy", "--stats", "1s", source, destination]);

2

我认为资源不起作用。进程是由操作系统创建的,而资源是由应用程序处理的。

一个可能的解决方案是在应用程序目录中捆绑其他可执行文件,并从该路径执行它们。


谢谢!您能指示如何将它们嵌入应用程序包(OSX)中吗?我想避免使用安装程序 - 简单的DMG映像应该是用户需要下载的全部。 - jan

0

所以问题似乎不在于从资源中提取git可执行文件,而更多地在于执行它?

git程序已经正确生成在磁盘上了,你能检查一下它的权限吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接