我有一个协议缓冲区协议,定义如下:
package pkg;
message Query {
optional uint32 basicfield = 1;
extensions 100 to max;
}
message Point {
optional int32 x = 1;
optional int32 y = 2;
}
message SpecificQuery {
oneof specific_oneof {
Point centre = 1000;
Point corner = 2000;
}
extend pkg.Query {
optional SpecificQuery specific_query = 101;
}
}
我使用的是Protocol Buffers 2.6.1rc1(我也使用2.6.0进行了测试),因为我想尝试使用oneof
功能。一切都是64位C++。make check
在两个平台上通过。如果我在Linux上发送和接收两者(使用gcc 4.6.3编译),它似乎可以正常工作。然而,如果我收到一个Mac(OSX 10.9,在XCode下使用Clang编译),它似乎无法识别扩展。
这是接收代码:
if (query.ParseFromArray(array, len))
{
if (query.has_basicfield())
{
printf("Basicfield: %d", query.basicfield());
}
if (query.HasExtension(pkg::SpecificQuery::specific_query))
{
// Never reached on OSX
// Reached on Linux
pkg::SpecificQuery* sqy = query.MutableExtension(pkg::SpecificQuery::specific_query);
if (sqy && sqy->specific_oneof_case() == pkg::SpecificQuery::kcentre)
{
// Also reached on linux
}
}
}
如果我用PrintDebugString()
打印Protocol Buffer对象,我会得到这个,正如Linux上预期的那样:
basicfield: 1234
[pkg.SpecificQuery.specific_query] {
centre {
x: 50
y: 150
}
}
但在Mac上,我看到:
basicfield: 1234
101 {
1000 {
1: 50
2: 150
}
}
此外,query._extensions_
为空,但query._unknown_fields_
包含101
,这表明扩展注册表似乎不起作用。有人知道为什么吗?
不知怎么的,SpecificQuery::specific_query
的定义没有链接到您的应用程序中。这可能是因为你的编译器非常聪明,它成功地优化了你对protobufs的所有调用,而你的链接器非常聪明,成功地从输出程序中删除了整个对象文件。如果.pb.o
以某种方式没有链接到程序中,那么它的初始化程序将永远不会运行,因此它定义的任何扩展都将永远不会注册,您将看到您所看到的行为。
强制链接的一种方法是在你知道正在正确链接的其他代码中放置一个伪用法
SpecificQuery::default_instance();
此函数调用没有副作用,但在.pb.cc
文件中实现,因此将强制链接.pb.o
。