协议缓冲区 - 生成非内联访问器

mik*_*ike 6 c++ windows protocol-buffers

我们在具有c#c ++代码的中型嵌入式系统中使用协议缓冲区(2.4.1).我们使用protobufs来隔离我们的托管和本机层,以及易于维护的序列化层(对于好奇,我们刚刚使用了Pinvoke,但我们还必须在测试/模拟器上的单独进程中运行本机代码).

我们的系统有许多DLL,我在它自己的DLL中有生成的本机protobuf代码,这样系统的其他部分就不必直接链接生成的代码.

我遇到的问题是所有生成的访问器都是内联的,例如:

inline const ::MyProtoClassName::MyField& MyProtoClassName::myfield() const 
{ 
   return myfield_ != NULL ? *myfield_ : *default_instance_->myfield_; 
}
Run Code Online (Sandbox Code Playgroud)

使用生成的API大小(如果未设置此特定字段,则取消引用并访问' default_instance_ ').这意味着我无法使用访问器链接(lnk2001)任何客户端,因为没有符号default_instance_

我认为ProtoBufs的典型用例是在生成的protobuf代码本身中包含每个组件链接(毕竟,这主要是分布式系统的序列化层),但是

我想知道是否有一个编译开关来改变我错过的内联行为.(在CC文件中定义所有访问器,而不是H)

谢谢!


  • 谢谢@ g-makulik!看起来答案是在ProtoC代码中大约30行,我只是没有看到它:)

    • <请参阅下面的答案,了解大部分解决方案>这也应该对您有所帮助.

正如Kenton的一些更改日志中所述,添加此项会导致与基础类相关的多个警告(C4251,c4275),这些警告也不是DLLEXPORT'd

通过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)  
Run Code Online (Sandbox Code Playgroud)

和一个包装器C文件(真正的protobuf CC文件不在我的项目中 - >不是直接构建的)

#include "MyProtoFile_WRAPPER.h"  
#include "MyProtoFile.cc"
Run Code Online (Sandbox Code Playgroud)

πάν*_*ῥεῖ 6

我认为这个链接可以回答你的问题:Protobuf与MSVC:如何导出生成的消息

引自Kenon Varga(谷歌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属性是内联的矛盾.