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

jan*_*jan 7 qt qprocess

我正在使用Qt编写一个跨平台的C++程序,我想在程序中打包/嵌入一些二进制可执行文件.该程序应该能够在运行时执行这些二进制文件.

我想,我需要使用start()和":/ ..."表示法的QResource和QProcess,但我似乎没有让进程运行.有什么我想念的吗?它应该像这样工作吗?二进制文件是否需要设置为可执行文件?

背景:我正在编写一个使用Git的工具,我不想让最终用户手动安装Git.

(在Mac OS X上尝试这个,BTW.)

更新:

我使用以下代码(C++,Mac OS X上的Qt):

QString program = ":/git";
QStringList arguments;
arguments << "help" << "commit";
myProcess->start(program, arguments);
Run Code Online (Sandbox Code Playgroud)

Git可执行文件位于项目路径中,我的resources.qrc引用它,如下所示:

<qresource prefix="/">
    <file>git</file>
</qresource>
Run Code Online (Sandbox Code Playgroud)

我没有收到错误,但程序没有执行.当我设置program为不存在的文件时,行为是相同的.":/git"用绝对路径替换git非常有效.

roh*_*npm 10

您无法直接从资源执行程序.

如果您在资源中有一个程序并且想要执行它,那么首先必须从资源中读取它,将其写入文件,使文件可执行,然后执行它.

此外,当您说您没有收到错误时,这可能意味着您没有正确检查错误.


Ken*_*sta 5

虽然已经晚了几年,但这个问题仍然具有现实意义。当我想嵌入rclone时遇到了同样的问题。

.pro文件中,添加

# From http://stackoverflow.com/a/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
}
Run Code Online (Sandbox Code Playgroud)

请注意,每个平台之间存在细微差别,但总的来说,方法是相同的。

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]);
Run Code Online (Sandbox Code Playgroud)