2013-07-31 33 views
5

我们在中等大小的嵌入式系统中使用协议缓冲区(2.4.1),带有c#和C++代码。我们使用protobufs来隔离我们的托管层和本地层,并提供易于维护的序列化层(为了好奇,我们只是使用了Pinvoke,但我们还必须在测试/模拟器的单独进程中运行本机代码)。协议缓冲区 - 生成非内联访问器

我们的系统有一些DLL,我在它自己的DLL中生成了native 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行了,我只是没有看到它:)

    • <请参阅下面的整体溶液的他的回答>这也应该帮助你,虽然。

正如一些肯顿的更新日志中指出,加入这会导致与基础类,是不是也DLLEXPORT'd

与方式ProtoBufs实现多次警告(C4251,c4275),和protobuf类是所有模板,这些警告是良性的。要干净地忽略它们(例如,不必禁用所有客户端的警告)我使用这个有点hacky的方法:

- eveyone包含的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

我在ProtoC代码中看到内联函数代码gen似乎只能从GenerateHeader(...)调用中调用......但我希望互联网已经解决了我面前的这个问题! :) – mike

回答

4

我觉得这个链接能回答你的问题:从Kenon瓦尔加(谷歌的protobuf的项目负责人)Protobuf with MSVC: how to export generated Message

报价:

如果您调用protoc像:

protoc --cpp_out = dllexport_decl = MY_EXPORT_MACRO:路径/到/输出/ DIR myproto.proto

那么它会在所有适当的地方生成MY_EXPORT_MACRO代码。但是,这个选项是不完整的 - 目前没有办法强制生成的.pb.h到#include一个定义MY_EXPORT_MACRO的头文件。我打开补丁来解决这个问题。或者,您可以使用hack来解决该问题,例如在protoc完成后通过某种文本处理添加#include,或者将.pb.h移动到.pb2.h并将.pb.h文件替换为一个包含第一那么你的标题包括.pb2.h ...

而且additonally覆盖提到不完备(引自阿隆比尔鲍姆):

目前,我们通过强制绕开这一限制使用编译器命令行标志包含标题为 :

Windows:/ FIproject/Con fig.h
的Linux:-include项目/ config.h中

注:
使用inline关键词不应该在这种情况下,相关的(即额外__declspec dllexport/__declspec dllimport属性被放在存取器方法)。根据定义,编译器需要内联函数。当然,看到__declspec dllexport__declspec dllimport属性是内联的相反词典。

+0

@mike THX接受。只是搜索了一下这个话题;-)。也许你应该用你提出的最终解决方案更新你的问题。它提供了更好的格式化选项,至少... –

+0

请在我的问题中看到我的“答案”以供我评论 - 所以我可以将它们格式化为可读格式。 – mike

+0

@mike看起来好多了! –