我们正在使用 google protobufs 在网络上传递数据。事物的服务器端类似于插件,因此处理 protobuf 消息的几个模块是 DLL。一些 DLL 依赖于其他 DLL,并使用其他的消息来定义自己的消息。
因此,A.DLL 具有a.proto
生成a.pb.h/cc
的消息类MsgA
。使用dllexport_decl
protoc 编译器上的未记录选项,消息类被声明为 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 库,我可能会在几天内回答第一点,但第二点超出了我目前的知识范围。我也希望得到一个快速向上或向下的答案,这可能会为我省去重新编译原型库的麻烦。