我需要将我的C ++程序连接到一对共享库,这些共享库会产生太多的输出到std::cout
和std::cerr
使得它们对于我的使用来说都是无用的。 我可以访问这些库的C ++源代码,但不能修改它们。
有没有办法将他们的输出redirect到一个不同的stream或抑制与我的代码链接? 我宁愿在C ++中使用干净的方式,但担心这是不可能的,我也会对肮脏的链接器黑客感到满意。 另外一个“代理libstdc++
”将是最后的手段罚款。
我正在Linux下使用GNU工具链( g++
, libtool
, ld
)。
那么似乎没有人打它,这里是我的连接建议:
write()
和过滤器输出到文件描述符1
和2
。 write()
。 dlsym()
绕过write()
的my_write()
函数。 -Wl,--wrap=write
链接共享库-Wl,--wrap=write
。 然后用一个名为__wrap_write
的函数来压缩任何输出到文件描述符1
和2
。 其他文件描述符应该调用__real_write
。 请注意,对于那些不知道,文件描述符1
和2
对应于最终写入cout
/ cerr
机器的stdout
和stderr
。 通常这是实现cout
调用fwrite
调用write
,不同级别的缓冲和shenanigans在不同级别。
你最好的选择是选择4,缺点是你必须调整共享库的最后一个链接。
接下来最好的是上面的选项2,缺点是你的最终可执行文件要大得多,但是不必在自己的代码中使用愚蠢的函数。
居间
包皮
显然, freopen可以做到这一点。
由于stdout(文件描述符1)和stderr(文件描述符2)在整个过程中都是有效的,并且不能让程序的一部分指向另一个文件,所以只有一种方法:使用dup(2)
复制它们并在你自己的代码中使用这些文件描述符。 关闭fd的1和2, open
/ dev / null进行写入,并使用dup2
尝试将它们分别设置为1或2(如果它尚未)。 相当丑陋,但那是行得通的。
如果你不需要自己使用,最简单的方法就是在启动程序的时候从命令行重定向标准输出和标准错误。
$ myprog >/dev/null 2>&1
如果你真的想自己使用它们,诀窍是改变它们使用的streambuf。 有一些关于如何在这里做的代码和讨论。 在这里张贴真的太久了。
三个想法(我真的很喜欢…):
您可以通过使用rdbuf()
更改正在写入的缓冲区cout
/ cerr
。 您可以在每次调用库中的函数之前执行此操作,然后重新设置(可能使用包装函数)。
您可以永久更改缓冲区,并为您自己的应用程序使用不同的cout / cerr对象。
您可以使用修改后的标准头文件来编译这些库。 他们可以定义新的全局流对象cout_new
并使用宏将cout
重新定义为cout_new
。 你可以告诉编译器使用新版本的头文件来编译库(所以你不必修改它们的源代码)。
正如我所说的,这些解决方案都不是“干净的”,但是你要求的是:)
如果他们真的通过std::cout
和std::cerr
输出,那么你可以替换那些对象的流缓冲区,但是你必须通过其他流重定向你自己的程序输出。 看到这个问题如何做到这一点。
但是,如果他们使用std::printf()
等,那么这将无法正常工作。