在Ubuntu上使用protobuf(C++)

2023-10-27

一、protobuf的下载和解压

protobuf提供了一些发布的版本,可以从里面下载指定语言的压缩包。

例如:

wget https://github.com/protocolbuffers/protobuf/releases/download/v21.7/protobuf-cpp-3.21.7.zip
unzip protobuf-cpp-3.21.7.zip
二、protobuf的安装

在上面解压的文件夹下,是有一个README.md文件的,里面介绍了安装的方式,主要是:

To build protobuf from source, the following tools are needed:

  • autoconf
  • automake
  • libtool
  • make
  • g++
  • unzip

On Ubuntu/Debian, you can install them with:

sudo apt-get install autoconf automake libtool curl make g++ unzip

To build and install the C++ Protocol Buffer runtime and the Protocol

Buffer compiler (protoc) execute the following:

./configure

make -j$(nproc) # $(nproc) ensures it uses all cores for compilation

make check

sudo make install

sudo ldconfig # refresh shared library cache.

By default, the package will be installed to /usr/local.

可以在终端上输入protoc --version查看安装成功与否。

三、使用示例

示例主要来自文件夹examples下的addressbook.proto

  • 定义protobuf源文件,addressbook.proto
// [START declaration]
syntax = "proto3";
package tutorial;

import "google/protobuf/timestamp.proto";
// [END declaration]

// [START messages]
message Person {
  string name = 1;
  int32 id = 2;  // Unique ID number for this person.
  string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;

  google.protobuf.Timestamp last_updated = 5;
}

// Our address book file is just one of these.
message AddressBook {
  repeated Person people = 1;
}
// [END messages]

这个文件主要的作用是定义了protobuf结构。

可以看到最后面,电话本(AddressBook)里面定义了Person结构,其repeated代表了电话本可以包含多个Person

  • 编译proto源文件

在源文件目录下执行以下编译命令:

protoc -I=. --cpp_out=. addressbook.proto

执行完后,会生成一个.cc和一个.h文件

在这里插入图片描述

生成的文件主要包含了结构体成员设置和格式转换的接口,下面展示一下如何使用。

  • 接口使用示例
  1. 测试写入文件testwrite.cc
#include <ctime>
#include <fstream>
#include <google/protobuf/util/time_util.h>
#include <iostream>
#include <string>

#include "addressbook.pb.h"

using namespace std;

using google::protobuf::util::TimeUtil;

// This function fills in a Person message based on user input.
void PromptForAddress(tutorial::Person *person)
{
  cout << "Enter person ID number: ";
  int id;
  cin >> id;
  person->set_id(id);
  cin.ignore(256, '\n');

  cout << "Enter name: ";
  getline(cin, *person->mutable_name());

  cout << "Enter email address (blank for none): ";
  string email;
  getline(cin, email);
  if (!email.empty())
  {
    person->set_email(email);
  }

  while (true)
  {
    cout << "Enter a phone number (or leave blank to finish): ";
    string number;
    getline(cin, number);
    if (number.empty())
    {
      break;
    }

    tutorial::Person::PhoneNumber *phone_number = person->add_phones();
    phone_number->set_number(number);

    cout << "Is this a mobile, home, or work phone? ";
    string type;
    getline(cin, type);
    if (type == "mobile")
    {
      phone_number->set_type(tutorial::Person::MOBILE);
    }
    else if (type == "home")
    {
      phone_number->set_type(tutorial::Person::HOME);
    }
    else if (type == "work")
    {
      phone_number->set_type(tutorial::Person::WORK);
    }
    else
    {
      cout << "Unknown phone type.  Using default." << endl;
    }
  }
  *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL));
}

// Main function:  Reads the entire address book from a file,
//   adds one person based on user input, then writes it back out to the same
//   file.
int main(int argc, char *argv[])
{
  // Verify that the version of the library that we linked against is
  // compatible with the version of the headers we compiled against.
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  if (argc != 2)
  {
    cerr << "Usage:  " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
    return -1;
  }

  tutorial::AddressBook address_book;

  {
    // Read the existing address book.
    fstream input(argv[1], ios::in | ios::binary);
    if (!input)
    {
      cout << argv[1] << ": File not found.  Creating a new file." << endl;
    }
    else if (!address_book.ParseFromIstream(&input))
    {
      cerr << "Failed to parse address book." << endl;
      return -1;
    }
  }

  // Add an address.
  PromptForAddress(address_book.add_people());

  {
    // Write the new address book back to disk.
    fstream output(argv[1], ios::out | ios::trunc | ios::binary);
    if (!address_book.SerializeToOstream(&output))
    {
      cerr << "Failed to write address book." << endl;
      return -1;
    }
  }

  // Optional:  Delete all global objects allocated by libprotobuf.
  google::protobuf::ShutdownProtobufLibrary();

  return 0;
}

通过以下命令编译,testread同理

g++ testwrite.cc addressbook.pb.cc -o testwrite -lprotobuf

运行可执行文件:

./testwrite addressbook.data

输入信息即可,查看addressbook.data,可以看到打包的数据。

在这里插入图片描述

  1. 测试读文件testread.cc:
#include <fstream>
#include <google/protobuf/util/time_util.h>
#include <iostream>
#include <string>

#include "addressbook.pb.h"

using namespace std;

using google::protobuf::util::TimeUtil;

// Iterates though all people in the AddressBook and prints info about them.
void ListPeople(const tutorial::AddressBook &address_book)
{
    for (int i = 0; i < address_book.people_size(); i++)
    {
        const tutorial::Person &person = address_book.people(i);

        cout << "Person ID: " << person.id() << endl;
        cout << "  Name: " << person.name() << endl;
        if (person.email() != "")
        {
            cout << "  E-mail address: " << person.email() << endl;
        }

        for (int j = 0; j < person.phones_size(); j++)
        {
            const tutorial::Person::PhoneNumber &phone_number = person.phones(j);

            switch (phone_number.type())
            {
            case tutorial::Person::MOBILE:
                cout << "  Mobile phone #: ";
                break;
            case tutorial::Person::HOME:
                cout << "  Home phone #: ";
                break;
            case tutorial::Person::WORK:
                cout << "  Work phone #: ";
                break;
            default:
                cout << "  Unknown phone #: ";
                break;
            }
            cout << phone_number.number() << endl;
        }
        if (person.has_last_updated())
        {
            cout << "  Updated: " << TimeUtil::ToString(person.last_updated()) << endl;
        }
    }
}

// Main function:  Reads the entire address book from a file and prints all
//   the information inside.
int main(int argc, char *argv[])
{
    // Verify that the version of the library that we linked against is
    // compatible with the version of the headers we compiled against.
    GOOGLE_PROTOBUF_VERIFY_VERSION;

    if (argc != 2)
    {
        cerr << "Usage:  " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
        return -1;
    }

    tutorial::AddressBook address_book;

    {
        // Read the existing address book.
        fstream input(argv[1], ios::in | ios::binary);
        if (!address_book.ParseFromIstream(&input))
        {
            cerr << "Failed to parse address book." << endl;
            return -1;
        }
    }

    ListPeople(address_book);

    // Optional:  Delete all global objects allocated by libprotobuf.
    google::protobuf::ShutdownProtobufLibrary();

    return 0;
}

运行可执行文件testread,读出addressbook.data中的信息,也就是反序列化。

./testread addressbook.data

output:

Person ID: 1
  Name: wzm
  E-mail address: 12345
  Mobile phone #: 11111
  Mobile phone #: sfafsa
  Mobile phone #: qqwq
  Mobile phone #: saf
  Updated: 2022-09-30T08:37:46Z
四、参考资料

关于proto源文件的写法及更多介绍,可以参考官方源码官方教程

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在Ubuntu上使用protobuf(C++) 的相关文章

随机推荐

  • ICLR 2022

    点击下方卡片 关注 CVer 公众号 AI CV重磅干货 第一时间送达 CrossFormer A Versatile Vision Transformer Based on Cross scale Attention CrossForme
  • 安卓架构组件实战——Lifecycle

    注 本文涉及代码请看 项目源码 Lifecycle是谷歌推出的一个架构组件 用于感知组件生命周期 并赋予了非组件对象感知生命周期的能力 Lifecycle组件用来响应另一个组件的生命周期状态变化 例如Activity和Fragment 可以
  • 软路由IP配置指南

    在网络设置中 正确地配置软路由IP是至关重要的一步 本文将以轻松风格为您提供详细解决方案 帮助您完成这个任务 并确保操作价值和专业度 随着互联网的普及 家庭或小型企业越来越需要强大而可靠的网络连接 使用软路由可以让我们更好地管理局域网内部流
  • 升级springboot2.0升级后出现的问题以及解决办法

    本来是准备升级springcloud的版本 Finchley RC1 gt Greenwich SR3 父模块的pom xml中springcloud版本由Finchley RC1升级到Greenwich SR3 对应的springboot
  • servlet获取表单数据

    Java servlet获取form表单数据 参数 在 Servlet 中如何使用 HttpServletRequest 获取请求参数和 request 对象传递数据有哪些方法 1 获取请求参数 在实际开发中 经常需要获取用户提交的表单数据
  • windows服务器tomcat部署Java项目并配置nginx

    下载安装jdk并配置环境变量 下载安装 百度网盘共享 win64位 提取码 1ytp 配置环境变量 第一步 配置JAVA HOME 值为JDK的安装目录 第二步 配置Path 需要注意Path路径一般是存在的 只需要追加即可 这里使用 JA
  • linux&树莓派开发——“交叉编译&软硬链接“ 工作中必然用到的技术 实现不同主机间交互开发

    交叉编译 一 交叉编译概念 二 为什么要交叉编译 交叉编译的基本知识 三 什么是交叉编译链 3 1 交叉编译链的命名规则 3 2 交叉编译工具链 交叉编译器 是什么 四 交叉编译工具链安装 1 临时有效 关闭窗口就无效了 2 永久有效 多少
  • 编写NodeJs脚本实现接口请求

    要编写运行脚本 需要先搭建开发环境 环境搭建 nodeJs脚本运行 当然需要先安装nodejs环境 官方地址在这里 nodejs官网 打开官网地址 可以看到下面一句话 Node js is an open source cross plat
  • 小程序权限设置:小程序下载图片保存到相册拒绝权限后,再次打开权限的解决方案

    小程序下载图片保存到相册功能 首次操作会提示 保存图片或视频到你的相册 有 拒绝 和 允许 两个选项 如果选择了拒绝就会保存失败 saveImageToPhotosAlbum fail auth deny 那么后续想打开该权限又该怎么操作呢
  • 今天才知道!华为手机摄像头可不止能拍照,它还能提高办公效率

    说起华为手机 大家首先想到的就是国产手机代表 拍照特别厉害 的确华为手机的拍照的确很厉害 但是你知道吗 华为手机的摄像头可不止能拍照哦 其实它还能提高工作效率 摄像头怎么办公 下面我们就一起看看吧 1 文档矫正功能 用相机拍摄文件 PPT幻
  • [Python系列-20]:爬虫 - urllib.request.urlopen(), 函数无法返回的解决办法

    作者主页 文火冰糖的硅基工坊 https blog csdn net HiWangWenBing 本文网址 https blog csdn net HiWangWenBing article details 119799484 最近是使用爬
  • SpringCloudAlibaba之Sentinel 熔断规则详解

    Sentinel 熔断降级简介 基本介绍 除了流量控制以外 对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一 一个服务常常会调用别的模块 可能是另外的一个远程服务 数据库 或者第三方 API 等 例如 支付的时候 可能需要远
  • 记录一次docker安装pxc的坑 (unknown option --ck)

    centos7 docker pxc 安装教程可以参考 https blog csdn net u013218587 article details 80863054 遇到的坑 navicat连接不上mysql 首先解决宿主机防火墙问题 最
  • 制造业数字化转型的实战路线图

    转载本文需注明出处 微信公众号EAWorld 违者必究 中国在2015年发布制造强国战略第一个十年的行动纲领 中国制造2025 这是中国部署全面推进实施制造强国的战略文件 按照 中国制造2025 的战略 中国正加快推动新一代信息技术和制造技
  • ChatGPT 真的太强大了!

    如果你问我 2023年最大的机会是什么 那一定是 ChatGPT 从2月份GPT3 5版本发布 到现在的4 0PLUS升级版 ChatGPT的迭代速度已经完全超过了我们的想象 它已经可以替代很多行业的工作 比如说 文案 程序 客服 设计 律
  • redis集群环境搭建以及java中jedis客户端集群代码实现

    最近项目中用到了redis 所以就找了相关的资料学习了 然后搭建了redis集群 以及客户端的java代码实现 由于对linux不太熟悉 所以在Linux上搭建redis集群的时候碰到了很多问题 下面就大概总结下 redis相关网站 官网
  • 内核中关于启动条件的英文说明整理

    内核中关于启动条件的说明 Kernel startup entry point This is normally called from the decompressor code The requirements are MMU off
  • MiniNet的安装与使用

    直接下载Openflow Tutorial中已经安装好mininet的虚拟机镜像 http www openflow org wk index php OpenFlow Tutorial 放在VMWare中直接运行起来即可 VMware自身
  • Leetcode刷题日志2.0

    目录 前言 1 数字的补数 2 最大连续 1 的个数 3 下一个更大元素 I 4 斐波那契数 5 提莫攻击 6 557 反转字符串中的单词 III 前言 今天就分享一下最近刷到的leetcode习题吧 编程语言 Python3 废话不多说
  • 在Ubuntu上使用protobuf(C++)

    一 protobuf的下载和解压 protobuf提供了一些发布的版本 可以从里面下载指定语言的压缩包 例如 wget https github com protocolbuffers protobuf releases download