我们正在使用谷歌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
有多个定义的事实是一个主要问题。
所以,最后,这是问题:
MsgA
的多个定义分散在整个DLL中是否真的安全?第一点,我可以在几天内解决自己,一旦我开始重建protobuf库,但第二点远远超出我目前的知识。我也希望得到快速上升或下降的答案,这可以省去重新编译原型库的麻烦。
答案 0 :(得分:1)
我在网络上使用了protobuffers用于RPC(Google也是这样做的 - 请参阅文档页面)。只要您对使用proto缓冲区的每个人都有类似的定义,一个定义就可以很好地反序列化由其他定义序列化的数据。事实上,只要你不重新分配标签号,旧版本的协议缓冲区定义就可以很好地与新版本交互(只要在流中存在反序列化定义中的“必需”字段,它就会成功)。
希望有所帮助。