Подавить вывод в cout из связанной библиотеки

Мне нужно связать мои программы на C ++ с парой общих библиотек, которые генерируют слишком много выходных данных для std :: cout и std :: cerr делает их обоих бесполезными для моего использования. У меня есть доступ к исходному коду C ++ этих библиотек, но я не могу их изменить.

Есть ли способ перенаправить их вывод в другой поток или подавить его, если он связан с моим кодом? Я бы предпочел чистый путь в C ++, но, опасаясь, что это будет невозможно, я также буду счастлив грязными хакерскими ссылками. Кроме того, «прокси libstdc ++ » подойдет в качестве крайней меры.

Я работаю с набором инструментов GNU ( g ++ , libtool , ld ) под Linux.

7
задан Benjamin Bannier 26 August 2010 в 14:24
поделиться

6 ответов

Ну, кажется, никто до этого не додумался, вот мои предложения компоновщика:

  1. Вставьте libc, предоставьте свой собственный write() и отфильтруйте вывод по файловым дескрипторам 1 и 2.
  2. Статически свяжите свой собственный код с libc, а затем вставьте общую версию для подавления write(), как указано выше.
  3. Вставить libc, предоставив функцию my_write(), которая обходит write() с помощью dlsym().
  4. Wrap write при связывании общих библиотек путем передачи -Wl,--wrap=write. Затем подавите любой вывод в файловые дескрипторы 1 и 2 в функции с именем __wrap_write. Другие файловые дескрипторы должны вызывать __real_write.

Обратите внимание, для тех, кто не знает, файловые дескрипторы 1 и 2 соответствуют stdout и stderr, которые в конечном итоге записано в механизме cout/cerr. Часто это реализуется cout вызовами fwrite, который вызывает write с различными уровнями буферизации и махинациями на разных уровнях.

Лучше всего выбрать вариант 4, недостатком которого является то, что вы должны настроить последнюю ссылку для общих библиотек.

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

Ссылки

Вставка

Обертывание

2
ответ дан 6 December 2019 в 22:59
поделиться

Три идеи (ни одна из которых мне не очень нравится...):

  • Вы можете изменить буфер cout/cerr, в который выполняется запись, используя rdbuf( ). Вы можете делать это каждый раз непосредственно перед вызовом функции в библиотеке и последующим ее сбросом (возможно, с помощью функций-оболочек).

  • Вы можете навсегда изменить буфер и использовать разные объекты cout/cerr для своего собственного приложения.

  • Для компиляции библиотек можно использовать модифицированные стандартные заголовочные файлы. Они могут определять новые объекты глобального потока cout_new и использовать макросы для переопределения cout на cout_new. Вы можете просто указать компилятору использовать новую новую версию файлов заголовков только для компиляции библиотек (так что вам не нужно изменять их исходный код).

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

1
ответ дан 6 December 2019 в 22:59
поделиться

Если они действительно выводят через std::cout и std::cerr, то вы можете заменить буферы потока этих объектов, но у вас будет для перенаправления вывода вашей собственной программы через другие потоки. См. этот вопрос , чтобы узнать, как это сделать.

Однако, если они используют std::printf() и т. д., это не сработает.

0
ответ дан 6 December 2019 в 22:59
поделиться

Поскольку stdout (файловый дескриптор 1) и stderr (файловый дескриптор 2) действительны для всего процесса, и вы не можете сделать так, чтобы одна часть программы указывала на другой файл, существует только один способ сделать это: использовать dup(2), чтобы продублировать их и использовать эти файловые дескрипторы в своем собственном коде. Закройте fd 1 и 2, open /dev/null для записи и используйте dup2, чтобы попытаться установить их в 1 или 2 соответственно, если это еще не сделано. Довольно некрасиво, но это сработает.

2
ответ дан 6 December 2019 в 22:59
поделиться

Если вам не нужно использовать ни то, ни другое, проще всего будет просто перенаправить стандартный вывод и стандартную ошибку из командной строки при запуске программы.

$ myprog >/dev/null 2>&1

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

2
ответ дан 6 December 2019 в 22:59
поделиться

Очевидно, freopen может это сделать.

4
ответ дан 6 December 2019 в 22:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: