我是protobuf(C ++)的新手,我的代码在解析我的消息时失败了。如何获得有关发生的错误的更多详细信息?
示例
以下代码段说明了问题:
const bool ok=my_message.ParseFromCodedStream(&stream);
if(ok){
std::cout<< "message parsed. evidence:\n"<< my_message.DebugString();
}
else{
std::cerr<< "error parsing protobuf\n";
//HOW CAN I GET A REASON FOR THE FAILURE HERE?
}
答案 0 :(得分:13)
如果您查看protobuf代码,您会发现它使用自己的日志系统 - 基于宏。默认情况下,所有这些邮件都发送到stderr
,但您可以使用SetLogHandler()
在程序中捕获它们:
typedef void LogHandler(LogLevel level, const char* filename, int line,
const std::string& message);
可能的解决方案是创建自己的errno
- 类似机制(对C ++ 11-ishness抱歉):
typedef LogMessage std::tuple<LogLevel, std::string, int, std::string>; // C++11
typedef LogStack std::list<LogMessage>;
namespace {
LogStack stack;
bool my_errno;
} // namespace
void MyLogHandler(LogLevel level, const char* filename, int line,
const std::string& message) {
stack.push_back({level, filename, line, message}); // C++11.
my_errno = true;
}
protobuf::SetLogHandler(MyLogHandler);
bool GetError(LogStack* my_stack) {
if (my_errno && my_stack) {
// Dump collected logs.
my_stack->assign(stack.begin(), stack.end());
}
stack.clear();
bool old_errno = my_errno;
my_errno = false;
return old_errno;
}
并在您的代码中使用它:
...
else {
std::cerr<< "error parsing protobuf" << std::endl;
LogStack my_stack;
if (GetError(&my_stack) {
// Handle your errors here.
}
}
我的示例代码的主要缺点 - 它不适用于多个线程。但这可以自己解决。
答案 1 :(得分:2)
有时错误信息会打印到控制台,但就是这样。没有办法通过API获得额外的错误信息。
尽管如此,反正只有两种错误:
如果您看到后一种情况,则需要比较发送方和接收方的数据,并找出原因不同的原因。请记住,您提供给protobuf解析器的数据不仅必须是相同的字节,而且必须在同一位置结束 - protobuf解析器除了通过接收EOF之外不知道消息的结束位置。这意味着如果要向流写入多条消息,则需要在数据之前写入大小,并确保在传递给protobuf解析器之前只读取接收端的那么多字节。