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