Замена вызова «system» в моей программе на C ++

0

Я пытаюсь найти замену для вызова "системы" (из stdlib.h) в моей программе C++. До сих пор я использовал его для вызова g++ в моей программе для компиляции, а затем связал переменное количество исходных файлов в каталоге, выбранном пользователем.

Здесь у меня есть пример, как команда может выглядеть примерно так: "C: /mingw32/bin/g++.exe -L" C:\mingw32\lib "[...]"

Однако у меня есть проблема, что (по крайней мере, с использованием компилятора MinGW, который я использую). Я получаю сообщение об ошибке "Командная строка слишком длинная", когда командная строка слишком длинная. В моем случае это было около 12000 символов. Поэтому мне, вероятно, нужен еще один способ позвонить g++. Кроме того, я читал, что вы вообще не должны использовать "систему": http://www.cplusplus.com/forum/articles/11153/

Поэтому я нуждаюсь в замене (это также должно быть как можно более независимым от платформы, потому что я хочу, чтобы программа работала на Windows и Linux). Я нашел одного кандидата, который обычно выглядит вполне подходящим:

  • _execv/execv:

    Независимо от платформы, но:

    a) http://linux.die.net/man/3/exec говорит: "Семейство функций exec() заменяет текущий образ процесса новым образцом процесса". Так что мне нужно сначала вызвать "fork", чтобы программа C++ не была завершена? Является ли вилка также доступной для Windows/MSVC?

    b) Используя "system", я проверил, было ли возвращаемое значение равным 0, чтобы узнать, можно ли скомпилировать исходный файл. Как это работает с exec? Если я правильно понял manpage, вернет ли он только успех создания нового процесса, а не статус g++? И с какой функцией я могу приостановить свою программу, чтобы дождаться завершения g++ и получить возвращаемое значение?

В общем, я не совсем уверен, как мне с этим справиться. Каковы ваши предложения? Как многоплатформенные программы, такие как Java (Runtime.getRuntime(). Exec (command)) или среда Eclipse C++ внутренне решают эту проблему? Что бы вы предложили мне сделать, чтобы называть g++ независимым от системы способом - с таким количеством аргументов, сколько я хочу?

EDIT: Теперь я использую следующий код - я тестировал его только в Windows, но, по крайней мере, он работает, как ожидалось. Спасибо за вашу идею, jxh! Возможно, я займусь сокращением команд, используя относительные пути в будущем. Тогда мне пришлось бы найти независимый от платформы способ изменения рабочего каталога нового процесса.

#ifdef WIN32
int success = spawnv(P_WAIT, sCompiler.c_str(), argv);
#else
pid_t pid;
switch (pid = fork()) {
case -1:
    cerr << "Error using fork()" << endl;
    return -1;
    break;
case 0:
    execv(sCompiler.c_str(), argv);
    break;
default:
    int status;
    if (wait(&status) != pid) {
        cerr << "Error using wait()" << endl;
        return -1;
    }
    int success = WEXITSTATUS(status);
}
#endif
  • 0
    fork() предназначен для систем POSIX, которые поддерживают вызов, а MINGW не реализует его для Windows. Должен быть файл заголовка <process.h> который обеспечивает spawn*() , который MINGW заменяет вызовы fork()/exec() .
  • 0
    Я боюсь спросить, почему вам нужно более 12 000 символов командной строки. Я прочитал рассказы, которые занимали меньше места.
Показать ещё 3 комментария
Теги:
exec
process
cross-platform

3 ответа

0
Лучший ответ

Вы можете получить некоторую тягу с некоторыми из этих параметров командной строки, если все ваши файлы находятся в (или могут быть перемещены) одним (или небольшим числом) каталогов. Учитывая ваш образец пути к audio.o, это уменьшит вашу командную строку примерно на 90%.

-Ldir
Add directory dir to the list of directories to be searched for '-l'.

От: https://gcc.gnu.org/onlinedocs/gcc-3.0/gcc_3.html#SEC17

-llibrary
Search the library named library when linking.

Это имеет значение, когда в команде вы пишете эту опцию; компоновщик ищет библиотеки процессов и объектные файлы в том порядке, в котором они указаны. Таким образом, foo.o -lz bar.o' searches library z' после файла foo.o' but before bar.o'. Если bar.o' refers to functions in z', эти функции могут не загружаться.

Компонент выполняет поиск стандартного списка каталогов для библиотеки, который на самом деле является файлом с именем liblibrary.a. Затем компоновщик использует этот файл, как если бы он был указан точно по имени.

Выбранные каталоги включают несколько стандартных системных каталогов плюс все, что вы указываете с помощью "-L".

Обычно файлы, найденные таким образом, являются библиотечными файлами - архивами, членами которых являются объектные файлы. Компилятор обрабатывает файл архива, просматривая его для членов, которые определяют символы, которые до сих пор ссылались, но не определялись. Но если найденный файл является обычным объектным файлом, он связан обычным образом. Единственная разница между использованием -L' option and specifying a file name is that -L 'окружает библиотеку с lib' and.a 'и ищет несколько каталогов.

От: http://gcc.gnu.org/onlinedocs/gcc-3.0/gcc_3.html

  • 1
    Кажется, это лучшее решение, поскольку оно переносимо, и вам не нужно добавлять какой-либо код для конкретной ОС. Спасибо за ваш ответ!
  • 1
    Я отметил ваш ответ как наиболее полезное решение, однако я не могу проголосовать за него, поскольку у меня пока нет «15 репутации».
0

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

Мне не очень нравится этот подход, так как вы должны возиться с окружающей средой, и я не знаю, повлияет ли это на ограничение командной строки. Может быть, предел применяется после интерполяции команды. Но, что-то об этом, независимо.

0

Вот еще один вариант, возможно, ближе к тому, что вам нужно. Попробуйте изменить каталог перед вызовом system(). Например, вот что происходит в Ruby... Я предполагаю, что он будет действовать одинаково в C++.

> system('pwd')
/Users/dhempy/cm/acts_rateable
=> true
> Dir.chdir('..')
=> 0
> system('pwd')
/Users/dhempy/cm
=> true

Ещё вопросы

Сообщество Overcoder
Наверх
Меню