Protobuf3 使用、入门教程及Demo

Protobuf简介

​ 简单设计协议, 通过自带工具转换成为对应的语言代码, 协议是二进制协议, 设计时只需要描述各个类的关系, 简单明了

用法:

  • 设计协议是在fileName.proto文件中, 其中fileName是自己定义, 在通过protoc转换成为对应的代码。

  • 关键字:

    • message 表示一个消息体, 相当于一个类。
    • 每个message中都有对应的变量, 每个变量有个对应的编号, 每个message内不同变量的编号不能重复。
    • 新版本的protobuf没有了required, optional等说明关键字, 都默认为optional
  • 基本语法

    //指定版本 使用protobuf3
    syntax = "proto3";
    
    message Account {
    	//账号
    	uint64 ID = 1;
    	//名字
    	string name = 2;
    	//密码
    	string password = 3;
    }
    

    ​ 语法很简单, 上面例子就是指定使用protob3, 然后定义了一个Account类, 里面包含ID, name, password, 对应的类型是 uint64, string, string。

    ​ 所以基本的语法规则跟C++类似。 只不过多了后面变量的编号。

  • 生成代码:

    需要生成什么语言的代码需要直接指定,例如C++

    protoc --cpp_out=./ project.proto

    protoc是工具名, 可以直接运行的命令。

    --cpp_out是参数, 指定生成C++代码, =后面指定生成的目录。

    project.proto是定义的文件。

    一共会生成两个文件。 project.pb.hproject.pb.cc

    其中有生成的Account类中有这几个设置属性的方法

    void clear_name();
    static const int kNameFieldNumber = 2;
    const std::string& name() const;
    void set_name(const std::string& value);
    void set_name(std::string&& value);
    void set_name(const char* value);
    void set_name(const char* value, size_t size);
    std::string* mutable_name();
    std::string* release_name();
    void set_allocated_name(std::string* name);
    
    // string password = 3;
    void clear_password();
    static const int kPasswordFieldNumber = 3;
    const std::string& password() const;
    void set_password(const std::string& value);
    void set_password(std::string&& value);
    void set_password(const char* value);
    void set_password(const char* value, size_t size);
    std::string* mutable_password();
    std::string* release_password();
    void set_allocated_password(std::string* password);
    
    // uint64 ID = 1;
    void clear_id();
    static const int kIDFieldNumber = 1;
    ::PROTOBUF_NAMESPACE_ID::uint64 id() const;
    void set_id(::PROTOBUF_NAMESPACE_ID::uint64 value);
    
    
    

    及get/set方法。

    可以直接操作该类的属性。

  • 使用该代码

    • 在要使用的代码中包含此头文件project.pb.h

      直接使用该对象即可。编译的时候需要把project.pb.cc编译, 并在链接的时候链接动态链接库 libprotobuf.so

  • demo

    #include <iostream>
    #include <string>
    #include "project.pb.h"
    
    
    int main()
    {
    	Account account;
    	account.set_id(1000);
    	account.set_name("name");
    	account.set_password("password");
    
    	//序列化
    	std::string s = account.SerializeAsString();
    	if(s.size() == 0) {
    		std::cout << "error in SerializeAsString" << std::endl;
    	}
    	Account nAccount;
        //反序列化
    	if(nAccount.ParseFromString(s)) {
    		std::cout << nAccount.id() << std::endl;
    		std::cout << nAccount.name() << std::endl;
    		std::cout << nAccount.password() << std::endl;
    	} else {
    		std::cout << "error in ParseFromString" << std::endl;
    	}
    
    	return 0;
    }
    
  • 编译

    project.pb.cc也需要编译, 如果是工程中, 可以单独编译, 由于只有一个文件所以就放到一块编译了g++ demo.cpp project.pb.cc -lprotobuf -o main

    输出结果为:

    1000

    name

    password

更复杂的demo

  • message的嵌套

    message就像类一样, 所以它也是可以嵌套的。

    可以直接在message内写, 也可以在外部写, 但是要注意的是, 一个message内的编号不能重复。

    所以令写一个message会节省编号。

    节省编号的所有是节省空间。 前15号(0~15)用一个字节, 后面以此类推, 两个三个字节, 所以前15编号比较珍贵。

  • demo

    //指定版本 使用protobuf3
    syntax = "proto3";
    
    message Account {
    	//账号
    	uint64 ID = 1;
    	//名字
    	string name = 2;
    	//密码
    	string password = 3;
    	//宠物狗
    	Dog dog = 4;
    }
    
    message Dog {
    	string name = 0;
    	bool sex = 1;
    }
    

    还有几个比较重要的方法

    set_allocated_dog dog不是必须的, 是类的名字。 可以是其他的名字

    • 参数是一个对应类型的指针, 调用这个函数, 它会自动释放这个指针的对象, 所以不需要delete, 否则会段错误。
    • 再次调用这个参数时, 如果之前已经设置过参数, 那么再次调用的时候会之前设置的属性删除, 并且delete越来的对象。 在设置成新的属性。

    除了这些方法之外还有一些clear之类的方法, 需要可以看文档或者给的头文件。

oneof

oneof 是设置多个属性中的一个, 例如, 我的宠物可以是狗, 也可以是猫, 但是每个人只有一个的话。 设置两个占的空间就有点大。 因此只需要有一个就够了, 所以这个oneof就像union一样。

//指定版本 使用protobuf3
syntax = "proto3";

message Account {
	//账号
	uint64 ID = 1;
	//名字
	string name = 2;
	//密码
	string password = 3;
	//宠物
	oneof pet {
		Dog dog = 4;
		Cat cat = 5;
	}
}

message Dog {
	string name = 1;
	bool sex = 2;
}

message Cat {
	string name = 1;
	//属性可以与Dog不同
}
  • 方法
    • has_cat 或者 has_dog 方法用于检测是否有cat/dog
    • 添加cat和dog直接用原来的方法添加即可。 但是当添加dog的时候会自动删除cat, 反之亦然。
  • 10
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值