如何将stdout重定向到stderr

How to redirect stdout to stderr

本文关键字:stderr 重定向 stdout      更新时间:2023-10-16

我正在使用一个同样使用JavaScript的C++QT应用程序。在C++中,我使用qDebug函数并使用qInstallMessageHandler捕获所有数据。

这将捕获指向stderr的所有内容。在JavaScript中,我使用的是console.info,它将数据写入stdout。

我想做的是将stdout重定向到stderr,这样console.info编写的所有消息都可以进入同一个消息处理程序。

void qDebugMsgHandler(QtMsgType type, const QMessageLogContext& context, const QString& strMsg) {
QString strOutput;
if ( context.file ) {
strOutput += QString(context.file);
if ( context.function ) {
if ( context.line > 0 ) {
strOutput += QString(" L%1").arg(context.line, 8, 10, QChar('0')) + QString(":");
}
strOutput += QString(context.function);
}
}
if ( strMsg.length() > 0 ) {
if ( strOutput.length() > 0 ) {
strOutput += ": ";
}
strOutput += strMsg;
}
switch( type ) {
case QtDebugMsg:
fprintf(stderr, "   Debug:%sn", strOutput.toLatin1().data());
break;
case QtInfoMsg:
fprintf(stderr, "    Info:%sn", strOutput.toLatin1().data());
break;
case QtWarningMsg:
fprintf(stderr, " Warning:%sn", strOutput.toLatin1().data());
break;
case QtCriticalMsg:
fprintf(stderr, "Critical:%sn", strOutput.toLatin1().data());
break;
case QtFatalMsg:
fprintf(stderr, "   Fatal:%sn", strOutput.toLatin1().data());
break;
}
fflush(stderr);
}

您可以使用ios:rdbuf。

示例:

#include <iostream>
int main() {
std::cout << "to stdoutn";
std::cout.rdbuf(std::cerr.rdbuf());
std::cout << "to stderrn";
}

出于我的目的,我最终在C++中创建了一个可调用的例程,它可以从JavaScript、C++原型调用:

Q_INVOKABLE void log(QString strMsg, QString strFile, long ulngLine);

C++实现:

void clsScriptHelper::log(QString strMsg, QString strFile, long ulngLine) {
QJsonObject json;
json["file"] = strFile;
json["line"] = QString("%1").arg(ulngLine);
json["msg"] = strMsg;
json["type"] = QString("%1").arg(QtDebugMsg);
qDebug() << json;
}

在JavaScript中,我通过对象引用"来公开我的C++层;api";,然后调用日志例程:

api.log("Testing", "SomeFile.js", 99);

消息处理程序现在看起来是这样的:

void qDebugMsgHandler(QtMsgType type, const QMessageLogContext& context, const QString& strMsg) {
static const QString scstrQJSONObject("QJsonObject(");
QString strFile, strFunction, strInfo, strOutput;
long lngLine = 0;
switch( type ) {
case QtDebugMsg:
strOutput = "   Debug:";
break;
case QtInfoMsg:
strOutput = "    Info:";
break;
case QtWarningMsg:
strOutput = " Warning:";
break;
case QtCriticalMsg:
strOutput = "Critical:";
break;
case QtFatalMsg:
strOutput = "   Fatal:";
break;
}
if ( strMsg.startsWith(scstrQJSONObject) ) {
//Message contains a JSON object, extract the details
int intLength = strMsg.length() - (scstrQJSONObject.length() + 1);
QString strJSON = strMsg.mid(scstrQJSONObject.length(), intLength);
QJsonDocument objDoc = QJsonDocument::fromJson(strJSON.toUtf8());
if ( objDoc.isNull() ) {
return;
}
QJsonObject objJSON = objDoc.object();
strFile = objJSON.take("file").toString();
lngLine = static_cast<long>(objJSON.take("line").toDouble());
strInfo = objJSON.take("msg").toString();
type = static_cast<QtMsgType>(objJSON.take("type").toInt());
} else {
strFile = QString(context.file);
if ( context.function ) {
strFunction = QString(context.function);
}
if ( context.line > 0 ) {
lngLine = context.line;
}
strInfo = strMsg;
}
if ( strFile.length() > 0 ) {
strOutput += strFile;
}
if ( lngLine > 0 ) {
strOutput += QString(" L%1").arg(lngLine, 8, 10, QChar('0')) + QString(":");
}
if ( strFunction.length() > 0 ) {
strOutput += strFunction;
}
if ( strInfo.length() > 0 ) {
if ( strOutput.length() > 0 ) {
strOutput += ": ";
}
strOutput += strInfo;
}
std::cout << strOutput.toLatin1().data() << std::endl << std::flush;
}