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

时间:2013-07-31 20:35:42

标签: 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_; 
}

使用生成的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"

1 个答案:

答案 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属性是内联的矛盾。