你可以静态地将相同的protobuf消息链接到多个DLL - 然后让这些DLL一起工作吗?

时间:2010-02-24 22:28:40

标签: c++ dll linker protocol-buffers

我们正在使用谷歌protobufs在线上传递数据。事物的服务器端是插件式的,因此处理protobuf消息的几个模块是DLL。一些DLL依赖于其他DLL并使用其他DLL来定义自己的消息。

因此,A.DLL有a.proto生成a.pb.h/cc消息类MsgA。使用protoc编译器上未记录的dllexport_decl选项,将消息类声明为DLL导出。

现在,B.DLL依赖于A.DLL,b.proto也看起来像这样:

import "a.proto";
message b 
{
    required int32 some_number = 1;
    required PackageA.MsgA some_a = 2;
}

最后,将部分拉到一起的可执行文件也取决于消息MsgA。 protobuf库也构建为DLL,并链接到所有内容。这一切都建立并运行。

但是,有光之力要求我们减少DLL分发!因此,我构建了模块A(它只是许多其他插件DLL使用的消息和小工具集合)作为静态库而不是DLL。 B.DLL和可执行文件都链接到A,一切都很好 - 到目前为止。

由于A是静态链接的,因此MsgA在所有DLL和EXE中完全定义。这没关系,因为生成的C ++代码中的所有静态数据都是const。那么,如果最终过程中有多个副本,那么所有副本都是相同的。

但是,当我运行新构建的进程时,libproto会抛出一个实际有用的异常 - MsgA的文件ID已经存在于描述符映射(或类似的东西)中。换句话说,MsgA 有多个定义的事实是一个主要问题。

所以,最后,这是问题:

  • 如果我们静态链接libproto而不是将其用作DLL,那么错误会消失吗?
  • MsgA的多个定义分散在整个DLL中是否真的安全?

第一点,我可以在几天内解决自己,一旦我开始重建protobuf库,但第二点远远超出我目前的知识。我也希望得到快速上升或下降的答案,这可以省去重新编译原型库的麻烦。

1 个答案:

答案 0 :(得分:1)

我在网络上使用了protobuffers用于RPC(Google也是这样做的 - 请参阅文档页面)。只要您对使用proto缓冲区的每个人都有类似的定义,一个定义就可以很好地反序列化由其他定义序列化的数据。事实上,只要你不重新分配标签号,旧版本的协议缓冲区定义就可以很好地与新版本交互(只要在流中存在反序列化定义中的“必需”字段,它就会成功)。

希望有所帮助。