8

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

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

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

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

最后,将各部分组合在一起的可执行文件也取决于 message 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 库,我可能会在几天内回答第一点,但第二点超出了我目前的知识范围。我也希望得到一个快速向上或向下的答案,这可能会为我省去重新编译原型库的麻烦。

4

1 回答 1

1

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

希望有帮助。

于 2011-04-23T17:19:32.847 回答