Как интегрировать программу C с открытым исходным кодом вместо вызова ее исполняемого файла через системный вызов?

У меня есть исполняемый файл (fossil scm), который вызывается моей программой извне через вызов Windows ::CreateProcess. Затем перехватываются stdout и stderr. Поскольку исходный код для ископаемого доступен, я бы предпочел создать из него статическую библиотеку и выполнять вызовы напрямую. В настоящее время связь с ископаемым осуществляется через параметры командной строки, а обратная связь — через код возврата процесса, stdout и stderr. Fossil пишет в stdout/err через вызовы printf и fprintf.

Каков наилучший способ решить эту проблему с минимальным изменением ископаемого источника? Есть ли надежный и кросс-платформенный способ перехвата stdout/err и отправки его в буфер памяти?


person ihamer    schedule 25.12.2010    source источник


Ответы (3)


Вы говорите, что хотите

перехватить stdout/err и отправить его в буфер памяти

Это будет означать, что вы не хотите вводить API для программы SCM, а вместо этого хотите продолжить синтаксический анализ текстового вывода без изменения существующего кода. Если это так, то я не вижу смысла менять ваш нынешний подход. Что именно можно получить, используя буфер памяти и статическое связывание по сравнению с текущим подходом?

person David Heffernan    schedule 25.12.2010
comment
Мне нравится не иметь дело с установкой другого исполняемого файла. Все еще оцениваю варианты, включая создание API и избежание проблем со стандартным выводом. - person ihamer; 03.01.2011

Вы можете сделать это поэтапно:

  • Переименуйте основную функцию ископаемого во что-то другое, чтобы вы могли вызвать ее
  • Прежде чем вызывать main ископаемого, перенаправьте stdout/stderr в файл по вашему выбору с помощью:

freopen("filename.out", "w", stdout);

  • Сформировать массив аргументов, вызвать ископаемое_main, прочитать вывод из файлов.
  • Вам нужно будет восстановить состояние потока stdout; для этого нет кросс-платформенного механизма, но вы можете использовать некоторые псевдо-дескрипторы (например, CONOUT$ в Windows).

Однако обратите внимание, что это хрупко:

  • Могут быть глобальные переменные, которые должны быть инициализированы нулями в начале main(), что не будет верно для второго вызова main().
  • ископаемый может изменить состояние какого-либо процесса/потока (локаль, текущий каталог и т. д.), вы не сможете надежно восстановить его. Особенно плохой случай — это вызов exit(n).
  • Не будет обычной очистки при завершении процесса - ожидайте дескрипторы файлов, которые остаются открытыми (чтобы вы не смогли открыть их снова, если они открыты без совместного использования), утечки памяти и т. д.
  • Очевидно, что теперь с вылетами/зависаниями в окаменелостях будет сложнее справляться (иногда это можно обойти)

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

person zeuxcg    schedule 25.12.2010

Превратите ископаемое в общую библиотеку, а затем используйте ее в своей пользовательской программе.

person user502515    schedule 25.12.2010