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;
编号 | C++数据类型 | 限制 | protobuf数据类型 | 备注 |
1 | bool | required | bool | |
2 | (unsigned) char | required | uint32 or int32 | protobuf 不支持char类型,建议使用int替代 |
3 | (unsigned) short | required | uint32 or int32 | protobuf 不支持short类型,建议使用int替代 |
4 | (unsigned) int | required | sfixed32 or fixed32 | |
5 | (unsigned) long | required | sfixed32 or fixed32 | 建议使用 int替代 |
6 | std::string | required | bytes | bytes可以更好的支持中文,protobuf string只支持asscii 不要使用char * ,char[] 等,使用std::string 替代 |
7 | 类对象 | required | 子message | 自定义类,而不是系统类对象,需要包含在同一个文件里面, 再次没有递归处理其他包含的头文件。后续可能支持 类被映射为一个消息(只映射一次) 并再次映射为消息的成员(子消息) |
8 | 指针类型,支持2种指针: shared_ptr weak_ptr |
optional | 根据T的实际类型进行映射 | T的类型为上面 编号1~7中的任意一种。 |
9 | 集合类型,包含一下几种: std::vector std::list std::set std::multiset |
required repeated |
bool include_${filename}字段 根据T的实际类型进行映射 |
包含一个bool类型的include字段,用于指示消息传递的过程中是 否包含本字段(protobuf repeated 字段存在二义性 ,在消息不包含repeated字段时,究竟时删除还是保留不变) T的类型为上面 编号1~8中的任意一种。 |
10 | map类型,包含2种: std::map std::multimap |
optional repeated repeated |
boo include_${filename} reptead KEY ${filename}_key reptead VALUE ${filename}_value |
KEY和VALUE各自映射为一个字段。在传输过程中, 通过下标一一匹配. KEY,VALUE的类型为上面 编号1~8中的任意一种。 |
#ifndef __FOCUS_ENTITY_H__
#define __FOCUS_ENTITY_H__
#include
#include
#include
#include
#include
#include
#ifdef N_ODB
#include
#include
#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 toZone( const shared_ptr & en)
{
return dynamic_pointer_cast(en);
}
inline shared_ptr toTerminal( const shared_ptr & en)
{
return dynamic_pointer_cast(en);
}
inline shared_ptr toUser( const shared_ptr & en)
{
return dynamic_pointer_cast(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
{
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 GetParent() const;
void SetParent(const shared_ptr & 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 CreateBuild() { return nullptr;}
#endif
void SendIndication();
protected:
void InternalSendIndcation();
private:
#pragma db id auto
unsigned int id_;
std::string name_;
weak_ptr parent_;
};
#pragma db object callback(dbevent) table("tblZone")
class CFocusZone : public CFocusEntity
{
friend class odb::access;
public:
CFocusZone();
~CFocusZone();
void AddEntity( const shared_ptr & en);
void DelEntity( const shared_ptr & en );
void dbevent( odb::callback_event e, odb::database& db );
void dbevent( odb::callback_event e, odb::database& db ) const;
shared_ptr FindEntity( unsigned int id, bool recursive = false) ;
shared_ptr FindEntity( const std::string & name, bool recursive = false) ;
#ifdef N_ODB
void foreach( const std::function & ) > & callback , bool recursive = false, bool isCallItself = false);
virtual shared_ptr CreateBuild();
#endif
static void SetRootZone( const shared_ptr & rootZone_);
static const shared_ptr & GetRootZone();
protected:
static shared_ptr rootZone;
private:
#pragma db inverse(parent_)
std::set< shared_ptr > members_;
std::set< int > int_members_;
std::set< CFocusEntity > raw_members_;
std::map< int ,shared_ptr > 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 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 CreateBuild();
#endif
protected:
private:
std::string password_;
};
#endif
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