我们在具有c#c ++代码的中型嵌入式系统中使用协议缓冲区(2.4.1)。我们使用protobufs来隔离我们的托管和本机层,以及易于维护的序列化层(对于好奇,我们刚刚使用了Pinvoke,但我们还必须在测试/模拟器上的单独进程中运行本机代码。)
我们的系统有许多DLL,我在其自己的DLL中生成了本机protobuf代码,这样系统的其他部分就不必直接链接到生成的代码中。
我遇到的问题是所有生成的访问器都是内联,例如:
inline const ::MyProtoClassName::MyField& MyProtoClassName::myfield() const
{
return myfield_ != NULL ? *myfield_ : *default_instance_->myfield_;
}
使用生成的API大小(如果未设置此特定字段,则取消引用并访问' default_instance _ ')。这意味着我无法使用访问器链接(lnk2001)任何客户端,因为没有符号default_instance_
我认为ProtoBufs的典型用例是在生成的protobuf代码本身中包含每个组件链接(毕竟,这主要是分布式系统的序列化层),但是
我想知道是否有编译开关来改变我错过的内联行为。 (在CC文件中定义所有访问器,而不是H)
谢谢!
谢谢@g-makulik!看起来答案是在ProtoC代码中大约30行,我只是没有看到它:)
正如Kenton的一些更改日志中所述,添加此项会导致与基础类相关的多个警告(C4251,c4275),这些警告也不是DLLEXPORT
实现ProtoBufs的方式,protobuf类是所有模板,这些警告是良性的。要彻底忽略它们(例如,不必为所有客户端禁用警告)我使用了这种有点hacky的方法:
-wrapone包含的protobuf.h文件的包装器。 (没有人包括真实生成的H文件)
#pragma once
#pragma warning(push)
#pragma warning(disable:4251)
#pragma warning(disable:4275)
// include the protobuf generated code; but exclude the warn c4251, c4275
// these relate to the dll exported
#include "yourProtoFile.h"
#pragma warning(pop)
和一个包装器C文件(真正的protobuf CC文件不在我的项目中 - >不是直接构建的)
#include "MyProtoFile_WRAPPER.h"
#include "MyProtoFile.cc"
答案 0 :(得分:5)
我认为此链接可以回答您的问题:Protobuf with MSVC: how to export generated Message
来自Kenon Varga(google protobuf的项目负责人)的引用:
如果您调用protoc:
protoc --cpp_out = dllexport_decl = MY_EXPORT_MACRO:path / to / output / dir myproto.proto
然后它将在所有正确的位置生成带有MY_EXPORT_MACRO的代码。但是,此选项不完整 - 目前无法强制生成的.pb.h #include定义MY_EXPORT_MACRO的标头。我愿意接受补丁来解决这个问题。或者,您可以使用hack来解决它,例如在protoc完成后通过某种文本处理添加#include,或者将.pb.h移动到.pb2.h并用.pb.h替换.pb.h文件首先包括你的标题然后包括.pb2.h ...
另外还要涵盖上述不完整性(引自Aron Bierbaum):
我们目前通过强制标头来解决这个问题 使用编译器命令行标志包含:
Windows:/FIproject/Config.h
Linux:-include project / Config.h
注意:强>
在这种情况下,使用inline
关键字不应该相关(在访问者方法上放置了额外的__declspec dllexport
/ __declspec dllimport
属性)。根据定义,编译器是否可以内联函数。当然,看到__declspec dllexport
或__declspec dllimport
属性是内联的矛盾。