C++ Class Mapped Google Protocol Buffer Message

本文介绍了一款用于简化Google Protocol Buffer使用的工具。该工具可以自动将C++类转换为Protocol Buffer消息定义,减少手动编写转换代码的工作量。同时,文章提供了具体的转换规则示例及测试案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 摘要
Google Protocol Buffer 是一个优秀的基于二进制的网络消息编解码框架。应用于项目时,可以节省不少的人力资源、开发时间和程序BUG。但其不足之处是protobuf编译器生成的C++消息类(或者Java等其他语言的消息类)冗余数据过多,需要依赖于protobuf的编解码库,一般情况下都不能用于作为业务逻辑对象。因此大部分情况下,程序都需要另外独立定义业务逻辑对象,并且使用protobuf定义相应(不一定100%相同)的消息,并手写代码,在protobuf消息对象和C++/Java业务对象之间进行转换。

protobuf消息还有另外一个缺点,是数据类型不够丰富,特别是指针,map集合不支持,你支持继承。通过required、optional属性的扩展可以让其支持指针,通过多字段,也可以让其支持map集合。

因在工程中,有太多的,太过于相似的转换代码,因此才有想法写一个C++类与google protobuf消息直接进行转换的工具。当然一次为蓝本,还可以转换为Java、C#等其他语言。当然转换后的代码不可能100%的可以直接工作,但是可以肯定的是已经完成了99%的工作,就剩下1%一点点的手动修改即可。

关于继承的映射。基类消息作为子类消息的第一个字段,明白字段名称为base;

  1. 数据类型映射规则
编号C++数据类型限制protobuf数据类型备注
1boolrequiredbool 
2(unsigned)  charrequireduint32  or int32protobuf 不支持char类型,建议使用int替代
3(unsigned) shortrequireduint32  or int32protobuf 不支持short类型,建议使用int替代
4(unsigned) intrequiredsfixed32 or fixed32 
5(unsigned) longrequiredsfixed32 or fixed32建议使用 int替代
6std::stringrequiredbytesbytes可以更好的支持中文,protobuf string只支持asscii
不要使用char * ,char[] 等,使用std::string 替代
7类对象required子message 自定义类,而不是系统类对象,需要包含在同一个文件里面,
再次没有递归处理其他包含的头文件。后续可能支持
类被映射为一个消息(只映射一次)
并再次映射为消息的成员(子消息)
8指针类型,支持2种指针:
shared_ptr<T>
weak_ptr<T>
optional 根据T的实际类型进行映射T的类型为上面 编号1~7中的任意一种。
9集合类型,包含一下几种:
std::vector<T>
std::list<T>
std::set<T>
std::multiset<T>
required
repeated
bool include_${filename}字段
根据T的实际类型进行映射
包含一个bool类型的include字段,用于指示消息传递的过程中是
否包含本字段(protobuf repeated 字段存在二义性
,在消息不包含repeated字段时,究竟时删除还是保留不变)
T的类型为上面 编号1~8中的任意一种。
10map类型,包含2种:
std::map<KEY,VALUE>
std::multimap<KEY,VALUE>
optional
repeated
repeated
boo include_${filename}
reptead KEY ${filename}_key
reptead VALUE ${filename}_value
KEY和VALUE各自映射为一个字段。在传输过程中,
通过下标一一匹配.
KEY,VALUE的类型为上面 编号1~8中的任意一种。

3. 自动化工具
工具使用Scala BNF语法进行构建,对C++头文件进行词法语法分析(主要分析类的声明和枚举的定义),并提取类的相关信息用于生成代码。
4.工具测试结果。
 4.1 测试内容
#ifndef __FOCUS_ENTITY_H__
#define __FOCUS_ENTITY_H__




#include <string>
#include <memory>
#include <set>

#include <odb/database.hxx>
#include <odb/tr1/memory.hxx>
#include <odb/callback.hxx>

#ifdef N_ODB
#include <Mutex.h>
#include <functional>
#include "Focus3800B.h"
#include "EntityBuild.h"
#endif
using std::tr1::shared_ptr;
using std::tr1::enable_shared_from_this;
using std::tr1::weak_ptr;
using std::tr1::dynamic_pointer_cast;

class CFocusEntity;
class CFocusZone;
class CFocusTerminal;
class CFocusUser;

inline shared_ptr<CFocusZone> toZone( const shared_ptr<CFocusEntity> & en)
{
    return dynamic_pointer_cast<CFocusZone,CFocusEntity>(en);
}
inline shared_ptr<CFocusTerminal> toTerminal( const shared_ptr<CFocusEntity> & en)
{
    return dynamic_pointer_cast<CFocusTerminal,CFocusEntity>(en);
}
inline shared_ptr<CFocusUser> toUser( const shared_ptr<CFocusEntity> & en)
{
     return dynamic_pointer_cast<CFocusUser,CFocusEntity>(en);
}
enum MsgNumPCtoTer {
  terminal_config = 1,
  network_basic_config = 2,
  timenow_config = 3,
  video_source_config = 16,
  video_output_config = 17,
  video_option_config = 18,
  network_advanced_config = 19,
  compatibility_config = 20,
  network_dial_config = 21,
  fire_wall_config = 22,
  communication_config = 23,
  video_config = 24,
  e1_config = 25,
  web_config = 26,
  command_config = 27,
  camera_select = 256,
  camera_advance = 257,
  camera_advance_active = 258,
  camera_up = 259,
  camera_down = 260,
  camera_left = 261,
  camera_right = 262,
  camera_near = 263,
  camera_far = 264,
  floor_apply = 512,
  chair_apply = 513,
  chair_release = 514,
  chair_viewed = 515,
  timer_preview = 516,
  auto_switch_time = 517,
  broacast_local = 518,
  force_exit = 519,
  volume_set = 520,
  mute_in_set = 521,
  mute_out_set = 522,
  dualstream_set = 523,
  conf_call_set = 524,
  accept_in_call = 525,
  reject_in_call = 526,
  conf_drop = 527,
  phone_modify = 528,
  phone_add = 529,
  feec_apply = 530,
  phone_histroy_del = 531,
  picture_show = 532,
  near_key = 533,
  far_key = 534,
  OK_key = 535,
  Ping = 768,
  video_loop = 769,
  restore = 770,
  out_test = 771,
  login_console = 1024,
  logout_console = 1025,
  restart = 1281
};

#pragma db object polymorphic callback(dbevent) table("tblEntity")
class CFocusEntity : public enable_shared_from_this<CFocusEntity>
{
    friend class odb::access;
public:
     CFocusEntity();
    virtual ~CFocusEntity();
    unsigned int GetId() const { return id_; }
    void SetId(unsigned int val) { id_ = val; }

    const std::string & GetName() const { return name_; }
    void SetName(const std::string & val) { name_ = val; }

    shared_ptr<CFocusZone> GetParent() const;
    void SetParent(const shared_ptr<CFocusZone> & val) { parent_ = val; }

    virtual void dbevent( odb::callback_event e, odb::database& db );
    virtual void dbevent( odb::callback_event e, odb::database& db ) const;

    bool persist();
    bool update();
    bool erase();
#ifdef N_ODB
    virtual shared_ptr<CProtobufEntityBuild> CreateBuild() { return nullptr;}
#endif
    void SendIndication();

protected:

    void InternalSendIndcation();
private:
#pragma db id auto
    unsigned int id_;
  
    std::string  name_;
   
    weak_ptr<CFocusZone> parent_;
  
};

#pragma  db object  callback(dbevent) table("tblZone")
class CFocusZone : public CFocusEntity
{
    friend class odb::access;
public:
    CFocusZone();
    ~CFocusZone();

    void AddEntity( const shared_ptr<CFocusEntity> & en);
    void DelEntity( const shared_ptr<CFocusEntity> & en );


    void dbevent( odb::callback_event e, odb::database& db );
    void dbevent( odb::callback_event e, odb::database& db ) const;

    shared_ptr<CFocusEntity> FindEntity( unsigned int id, bool recursive = false) ;
    shared_ptr<CFocusEntity> FindEntity( const std::string & name, bool recursive = false) ;
#ifdef N_ODB
    void foreach( const std::function<void( const shared_ptr<CFocusEntity> & ) > & callback  , bool recursive = false, bool isCallItself = false);
    virtual shared_ptr<CProtobufEntityBuild> CreateBuild();

#endif    
    static void SetRootZone( const shared_ptr<CFocusZone> & rootZone_);

    static const shared_ptr<CFocusZone> & GetRootZone();
protected:
    static shared_ptr<CFocusZone> rootZone;
private:
#pragma db inverse(parent_)
    std::set< shared_ptr<CFocusEntity> > members_;
		std::set< int > int_members_;    	
	  std::set< CFocusEntity > raw_members_;
	  	
	  std::map< int ,shared_ptr<CFocusEntity> > map_members_;
		std::map< int ,int > map_int_members_;    	
	  std::map< int ,CFocusEntity > map_raw_members_;
	  	

#ifdef N_ODB
    mutable dv::CMutex members_mutex;
#endif

};

#pragma db object callback(dbevent) table("tblTerminal")
class CFocusTerminal : public CFocusEntity
{
    friend class odb::access;
public:
    CFocusTerminal();
    ~CFocusTerminal();

    const std::string & GetAddress() const { return address_; }
    void SetAddress(const std::string & val) { address_ = val; }

    unsigned short GetPort() const { return port_; }
    void SetPort(unsigned short val) { port_ = val; }

    const std::string & GetUsername() const { return username_; }
    void SetUsername(const std::string & val) { username_ = val; }

    const std::string & GetPassword() const { return password_; }
    void SetPassword(const std::string & val) { password_ = val; }




    void dbevent( odb::callback_event e, odb::database& db );
    void dbevent( odb::callback_event e, odb::database& db ) const;

    void keepalive_init();

    

    void clear_status();

    void send_keepalive();

    void remote_login();

    void release_connect();

    bool IsOnline() const { return recv_service_ok_;}
#ifdef N_ODB
    void OnRecvMessage( T_Message &recvMsg );
   // bool IsDualEnable() const { return IsOnline () && dual_stream_status_ ;}
    bool IsLogin() const { return remote_login_ok_; }
    //bool IsAdmin() const { return remote_login_ok_ && adminstartor_ok_;}
    virtual shared_ptr<CProtobufEntityBuild> CreateBuild();
    void SetDualEnable( DualLevel level );
    //bool IsInConfing() const { return conf_status_.ConfStatus > 0 ? true : false;}
    void SetCommand( unsigned long ulCommand);
    void DisConnect();
    const T_InformTerConfig & GetTerConfig() const { return ter_config_;}
    const T_InformSysStatus & GetSysStatus() const { return sys_status_;}
    const T_InformConfStatus & GetConfStatus() const { return conf_status_;}
    //const T_InformVideoConfig & GetVideoConfig() const { return video_config_; }
    const T_VideoOption & GetVideoOption() const { return video_option_; }
    const T_SetupSoftware & GetSoftwareVersion() const { return software_version_; }
    void clear_resource();
    bool CanSendMediaInfo() const { return is_recv_sys_status_;}

    unsigned int GetValveRecvRate() const { return valveRecvRate_; }
    void SetValveRecvRate(unsigned int val) { valveRecvRate_ = val; }

    unsigned int GetValveSendRate() const { return valveSendRate_; }
    void SetValveSendRate(unsigned int val) { valveSendRate_ = val; }

    unsigned int GetValveRecvFrame() const { return valveRecvFrame_; }
    void SetValveRecvFrame(unsigned int val) { valveRecvFrame_ = val; }

    unsigned int GetValveSendFrame() const { return valveSendFrame_; }
    void SetValveSendFrame(unsigned int val) { valveSendFrame_ = val; }

    unsigned int GetValveLostRate() const { return valveLostRate_; }
    void SetValveLostRate(unsigned int val) { valveLostRate_ = val; }
#endif
    const std::string & GetH323id() const { return h323id_; }
   // void SetH323id(std::string val) { h323id_ = val; }

    const std::string & GetE164() const { return e164_; }
    //void SetE164(std::string val) { e164_ = val; }
    unsigned int GetNo() const { return No_; }
    void SetNo(unsigned int val) { No_ = val; }

    const std::string & GetContacter() const { return contacter_; }
    void SetContacter(const std::string &  val) { contacter_ = val; }

    const std::string &  GetPhone() const { return phone_; }
    void SetPhone(const std::string &  val) { phone_ = val; }
private:
    std::string    address_;
   
    unsigned short port_;
    std::string username_;
    std::string password_;
    unsigned int No_;   
    std::string contacter_;   
    std::string phone_;
    unsigned int valveRecvRate_ ;
    unsigned int valveSendRate_;
    unsigned int valveRecvFrame_;
    unsigned int valveSendFrame_;
    unsigned int valveLostRate_;
  
#pragma db transient
    unsigned int connect_id_;
#pragma db transient
    unsigned int timer_id_;
#pragma db transient
    bool  recv_service_ok_;
#pragma db transient
    bool  remote_login_ok_;
#pragma db transient
    bool  adminstartor_ok_;
#pragma db transient
    bool dual_stream_status_;
#pragma db transient
    std::string h323id_;
  
#pragma db transient
    std::string e164_;
    
#ifdef N_ODB
    T_InformTerConfig ter_config_;
    T_InformSysStatus sys_status_;
    T_InformConfStatus conf_status_;
    T_VideoOption video_option_;
    T_Message     lastRecvMsg_;
    T_SetupSoftware software_version_;
    bool is_recv_sys_status_;
#endif
};

#pragma db object callback(dbevent) table("tblUser")
class CFocusUser : public CFocusEntity
{
    friend class odb::access;
public:
     CFocusUser();
    ~CFocusUser();

    const std::string & GetPassword() const { return password_; }
    void SetPassword(const std::string & val) { password_ = val; }

    void dbevent( odb::callback_event e, odb::database& db );
    void dbevent( odb::callback_event e, odb::database& db ) const;
#ifdef N_ODB
    virtual shared_ptr<CProtobufEntityBuild> CreateBuild();
#endif
protected:
   
private:
    std::string password_;
};
#endif

4.2输出结果
package pbmsg;
 enum MsgNumPCtoTer
 {
terminal_config = 1;
network_basic_config = 2;
timenow_config = 3;
video_source_config = 16;
video_output_config = 17;
video_option_config = 18;
network_advanced_config = 19;
compatibility_config = 20;
network_dial_config = 21;
fire_wall_config = 22;
communication_config = 23;
video_config = 24;
e1_config = 25;
web_config = 26;
command_config = 27;
camera_select = 256;
camera_advance = 257;
camera_advance_active = 258;
camera_up = 259;
camera_down = 260;
camera_left = 261;
camera_right = 262;
camera_near = 263;
camera_far = 264;
floor_apply = 512;
chair_apply = 513;
chair_release = 514;
chair_viewed = 515;
timer_preview = 516;
auto_switch_time = 517;
broacast_local = 518;
force_exit = 519;
volume_set = 520;
mute_in_set = 521;
mute_out_set = 522;
dualstream_set = 523;
conf_call_set = 524;
accept_in_call = 525;
reject_in_call = 526;
conf_drop = 527;
phone_modify = 528;
phone_add = 529;
feec_apply = 530;
phone_histroy_del = 531;
picture_show = 532;
near_key = 533;
far_key = 534;
OK_key = 535;
Ping = 768;
video_loop = 769;
restore = 770;
out_test = 771;
login_console = 1024;
logout_console = 1025;
restart = 1281;
};

message CFocusEntity
{

optional fixed32 id = 1;
required bytes name = 2; 
optional CFocusEntity parent = 3;
};
      

message CFocusZone
{
required CFocusEntity base = 1;

optional bool include_members = 2;
repeated CFocusEntity members =3;
        

optional bool include_int_members = 4;
repeated sfixed32 int_members =5;
        

optional bool include_raw_members = 6;
repeated CFocusEntity raw_members =7;
        

optional bool include_map_members = 8;
repeated sfixed32 map_members_key =9;
repeated CFocusEntity map_members_value =10;
        

optional bool include_map_int_members = 11;
repeated sfixed32 map_int_members_key =12;
repeated sfixed32 map_int_members_value =13;
        

optional bool include_map_raw_members = 14;
repeated sfixed32 map_raw_members_key =15;
repeated CFocusEntity map_raw_members_value =16;
        
};
      

message CFocusTerminal
{
required CFocusEntity base = 1;
required bytes address = 2; 
optional uint32 port = 3;
required bytes username = 4; 
required bytes password = 5; 
optional fixed32 No = 6;
required bytes contacter = 7; 
required bytes phone = 8; 
optional fixed32 valveRecvRate = 9;
optional fixed32 valveSendRate = 10;
optional fixed32 valveRecvFrame = 11;
optional fixed32 valveSendFrame = 12;
optional fixed32 valveLostRate = 13;
optional fixed32 connect_id = 14;
optional fixed32 timer_id = 15;
optional bool recv_service_ok = 16;
optional bool remote_login_ok = 17;
optional bool adminstartor_ok = 18;
optional bool dual_stream_status = 19;
required bytes h323id = 20; 
required bytes e164 = 21; 
};
      

message CFocusUser
{
required CFocusEntity base = 1;
required bytes password = 2; 
};
      
    

Process finished with exit code 0


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值