我有一个使用C ++库的Qt / C ++应用程序。
此库具有将字符串消息写入标准错误的日志机制。
现在,我希望能够将这些消息重定向到我的Qt工具中的面板。 我想避免修改库,因为许多其他客户端都采用了它。 知道如何在运行时获取这些消息吗?
相反,改变它的可能性将这些消息传递给应用程序可能是一个好的做法?
答案 0 :(得分:4)
这是非常糟糕的图书馆设计。然而...
它如何写入标准错误。如果输出到std::cerr
,
然后,您可以更改streambuf
使用的std::cerr
,例如:
std::filebuf logStream;
if ( ~logStream.open( "logfile.txt" ) )
// Error handling...
std::streambuf* originalCErrStream = std::cerr.rdbuf();
std::cerr.rdbuf( &logStream );
// Processing here, with calls to library
std::cerr.rdbuf( originalCErrStream ); // Using RAII would be better.
不要忘记恢复原始的streambuf;离开std::cerr
指向已被破坏的filebuf
不是一个好主意。
如果他们使用的是FILE*
,那么C中就会有一个freopen
函数
你可以使用包含在C ++中)。
如果他们在Unix下使用系统级输出(write
,WriteFile
在Windows下,那么你将不得不使用一些系统级代码
改变输出。 (open
在新文件上,close
在fd上
STDERR_FILENO
和dup2
设置STDERR_FILENO
以使用新版本
在Unix下打开文件。我不确定它是否可能
Windows - 可能是ReOpenFile
或某种组合的东西
CloseHandle
后跟CreateFile
。)
编辑:
我刚注意到你实际上想要输出到Qt窗口。这个
意味着你可能需要一个字符串,而不是一个文件。如果
库正在使用std::cerr
,您可以使用std::stringbuf
而不是std::filebuf
一个sync
;事实上,你可能想要创建自己的streambuf,
接听<<
的呼叫(通常在每次呼叫后调用)
std::cerr
上的read()
。如果库使用其他技术之一,
我唯一能想到的是定期读取文件,看看
如果有任何添加的话。 (我会在Unix中使用ReadFile()
,FILE*
在Windows中为此,以确保能够区分
读取零字节,因为自上次以来没有写入任何内容
读取和错误条件。 {{1}}和iostream函数处理一个
读取零字节作为文件结尾,不再读取。)
答案 1 :(得分:2)
写入stderr实际上是一个系统调用:
write(2, "blahblah ...");
您可以将文件描述符编号2重定向到任何内容(文件,管道,套接字):
close(2); // close old stderr
int redirect_target = open(...); // open a file where you want to redirect to
// or use pipe, socket whatever you like
dup2(redirect_target, 2); // copy the redirect_target fd to fd number 2
close(redirect_target);
在你的情况下,你需要一个烟斗。
close(2);
int pipefd[2];
pipe2(pipefd);
dup2(pipefd[1], 2);
close(pipefd[1]);
然后,可以通过读取pipe [0]来获取写入stderr的所有内容:
read(pipe[0], buffer, ...);
答案 2 :(得分:1)
如果他们正在使用std::cerr
来电,您可以将其重定向到std::ostringstream
。
#include <iostream>
#include <sstream>
class cerr_redirector
{
public:
cerr_redirector(std::ostream& os)
:backup_(std::cerr.rdbuf())
,sbuf_(os.rdbuf())
{
std::cerr.rdbuf(sbuf_);
}
~cerr_redirector()
{
std::cerr.rdbuf(backup_);
}
private:
cerr_redirector();
cerr_redirector(const cerr_redirector& copy);
cerr_redirector& operator =(const cerr_redirector& assign);
std::streambuf* backup_;
std::streambuf* sbuf_;
};
您可以使用以下方式捕获输出:
std::ostringstream os;
cerr_redirector red(os);
std::cerr << "This is written to the stream" << std::endl;
std::cout
将不受影响:
std::cout << "This is written to stdout" << std::endl;
因此,您可以测试您的捕获是否有效:
std::cout << "and now: " << os.str() << std::endl;
或者只是将os.str()
的内容添加到您的Qt窗口。
答案 3 :(得分:0)
在这里,我找到了我需要的完整实现... 感谢大家的帮助! :)
Will loading a DLL dynamically reconcile its stderr to a main application? If so, then how...?