Как мне встроить двоичный исполняемый файл (для выполнения во время выполнения) в программу Qt? - PullRequest
7 голосов
/ 21 декабря 2009

Я пишу кроссплатформенную программу на C ++, используя Qt , и я хочу упаковать / встроить несколько двоичных исполняемых файлов в программу. Программа должна иметь возможность выполнять эти двоичные файлы во время выполнения.

Я подумал, что мне понадобятся 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 работает отлично.

Ответы [ 4 ]

9 голосов
/ 22 декабря 2009

Вы не можете запустить программу напрямую из ресурса.

Если у вас есть программа в ресурсе, и вы хотите ее выполнить, вам сначала нужно прочитать ее из ресурса, записать в файл, сделать файл исполняемым, а затем выполнить.

Кроме того, когда вы говорите, что не получаете сообщение об ошибке, это, вероятно, означает, что вы не проверяете ошибки должным образом.

3 голосов
/ 15 марта 2017

Несколько лет спустя, но вопрос все еще актуален. У меня была такая же проблема при желании вставить 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
}

Обратите внимание, что существуют небольшие различия для каждой платформы, но в целом подход тот же.

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 голосов
/ 21 декабря 2009

Я не думаю, что ресурсы будут работать. Процессы создаются операционной системой, а ресурсы обрабатываются приложением.

Одним из возможных решений было бы объединение дополнительных исполняемых файлов где-нибудь в каталоге вашего приложения и выполнение их по этому пути.

0 голосов
/ 22 декабря 2009

То есть проблема не в том, чтобы извлечь исполняемый файл git из ресурса, а в том, что он выполняется?

Программа git правильно генерирует диск, можете проверить его права?

...