OSX上无法识别协议缓冲区扩展

时间:2014-10-16 14:41:22

标签: c++ encoding cross-platform protocol-buffers messages

我有一个协议缓冲区协议定义如下:

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,表示扩展注册表似乎无效。有谁知道为什么?

1 个答案:

答案 0 :(得分:2)

不知何故,SpecificQuery::specific_query的定义未与您的应用相关联。可能是你的编译器非常聪明,它设法优化了你对protobufs所做的所有调用,而你的链接器非常聪明,它设法从输出程序中删除整个目标文件。如果你.pb.o以某种方式没有链接到程序中,那么它的初始化程序将永远不会运行,因此它定义的任何扩展都不会被注册,你会看到你所看到的行为。

强制链接的一种方法是在您知道正确链接的其他代码中放置虚拟用法。例如,您可以将此行添加到您发布的函数中:

SpecificQuery::default_instance();

此函数调用没有副作用,但在.pb.cc文件中实现,因此将强制.pb.o链接。