【c++】14.编译proto和proto相关用法

2023-11-18

编译proto和proto相关用法

关于proto相关的知识可以参考系列博客 https://blog.csdn.net/daaikuaichuan/category_9869251.html

【xx.proto文件中如果要注释的话,注释符号也是双斜杠"//"】

1.编译proto的问题

重装protoc可参考 https://blog.csdn.net/u013498583/article/details/74231058

查看当前protoc版本: protoc --version

查看protoc安装位置:which protoc

查找protoc相关文件:sudo find / -name protoc

编译proto文件
protoc caffe.proto --cpp_out=./ 生成caffe.pb.h、caffe.pb.cc文件
protoc caffe.proto --python_out=./ 生成caffe_pb2.py文件
假如环境中装了一个以上的protoc版本,可使用protoc双击tab键,会弹出所有版本(protoc protoc_2.6.1,其中protoc是默认版本,protoc --version是查看当前默认protoc版本)。
如果我们要使用非默认版本protoc编译proto,可以protoc_2.6.1 caffe.proto --cpp_out=./这种方式编译。
在编译MobileNet-YOLO工程时,使用protoc protoc_2.6.1编译后的 caffe.pb.hcaffe.pb.cc 文件粘贴到 caffe\include\caffe\proto即可。

----------------------------------------------------------------------------------------

2.proto相关函数用法

如果有一个proto_name结构的 proto消息:

2.1 set_xx(value)、 add_xx()、 mutable_xxx()

proto_name.set_xx(value) 该函数给对应的变量赋值

proto_name.add_xx() 该函数给对应的repeated变量增加一个xx类型的元素,返回值为指针类型。一般用法为:在for循环中调用一次,proto消息就添加一个该类型数据。

proto_name.mutable_xxx() 该函数返回指向该字段的一个指针,同时将该字段置为被设置状态。若该对象存在,则直接返回该对象,若不存在则新new 一个。

----------------------------------------------------------------------------------------
2.2 SerializeToString、ParseFromString、SerializeToArray、ParseFromArray、CopyFrom、IsInitialized、

例如,有 proto_name.proto文件,把这个 proto_name.proto文件编译后,会产生 proto_name.pb.hproto_name.pb.cc, 生成的.h文件中的class都继承自::google::protobuf::Message类,Message类提供了一些方法可以检查或者操作整个message,包括:

bool IsInitialized() const; 检查是否所有required变量都已经初始化;

string DebugString() const; 返回message的可阅读的表示,主要用于调试程序;

void CopyFrom(const Person& from); 使用一个message的值覆盖本message;

void Clear(); 清空message的所有成员变量值。

----------------------------------------------------------------------------------------

每个message类都提供了写入和读取message数据的方法,包括

bool SerializeToString(string* output) const; // 把message编码进output。

bool ParseFromString(const string& data); // 从string解码到message

bool SerializeToArray(char* buf,int size) const; // 把message编码进数组buf.

bool ParseFromArray(const char* buf,int size); // 把 buf解码到message。此解码方法效率较ParseFromString高很多,所以一般用这种方法解码。

bool SerializeToOstream(ostream* output) const; // 把message编码进ostream

bool ParseFromIstream(istream* input); // 从istream解码到message

备注:发送接收端所使用的加码解码方法不一定非得配对,即发送端用SerializeToString 接收端不一定非得用ParseFromString ,可以使用其他解码方法。

----------------------------------------------------------------------------------------
一般使用 bool SerializeToString(string* output) const;bool SerializeToArray(char* buf,int size) const;

例如当需要使用tcp/udp发送包含数组的时候,建议使用 bool SerializeToArray(char* buf,int size) const;,因为涉及到 数据包头、校验位之类的需要使用数组索引的方式,这样最好使用SerializeToArray

#define _fill_pack(name)                                                    \
  {                                                                         \
    char tbuf[256 * 1024];                                                  \
    uint32_t len = name.ByteSize();                                         \
    auto header = name.header();                                            \
    _fill_pack_head(static_cast<uint32_t>(netproxy_##name##_pack), len,     \
                    reinterpret_cast<netproxy_pack_t *>(tbuf));             \
    if (!name.SerializeToArray(&tbuf[sizeof(netproxy_pack_t)], len)) {      \
      SERROR << "serialize error, name:" << #name << " len:" << len;        \
      len = -sizeof(netproxy_pack_t);                                       \
    }                                                                       \
    Send_data(tbuf, len + sizeof(netproxy_pack_t), netproxy_##name##_pack); \
  }

其他时候可以直接使用SerializeToString

----------------------------------------------------------------------------------------
用法1:对外接口的消息结构的兼容性

当某个对外接口的消息结构 msgA 中的某个变量的结构总是要根据需求而频繁增删修改的时候,一般会在这个消息结构 msgA 中定义一个std::string proto_data的变量,
这样只需要修改proto_name.proto文件中的内容,而不需要总是修改 msgA(尤其是当修改msgA可能需要修改框架协议的时候,总之就是代价比较大),使用proto方法来解决这个问题就特别方便。

原始结构:

struct msgA{
    MsgHeader header;
    bool is_ok;
    structBBB msgbbb;  //当这个结构体 structBBB 增删修改结构比较麻烦时,会造成频繁修改对外接口 msgA 的麻烦。
}
方法:

先定义一个 proto_name.proto文件,把这个 proto_name.proto文件编译后,会产生 proto_name.pb.hproto_name.pb.cc,
对其中定义的变量赋值是使用 set_xxx(111) 函数进行赋值,赋值完成后再序列化之后进行打包发送;
发送之前使用 proto_name.SerializeToString(&data) 把该 结构序列化为string类型,然后再发送。
原始结构 修改为:

struct msgA{
    MsgHeader header;
    bool is_ok;

   //定义一个string类型的结构来代替 structBBB msgbbb; 然后把proto定义的数据结构 proto_name.proto赋值后,
   //调用 proto_name.SerializeToString(proto_data) 进行序列化转换为string赋值给proto_data变量,这就是使用proto方式来解决。
    std::string proto_data;   
}

下面的函数,我们封装了proto自带的SerializeToString和ParseFromString方法

// msg转换成string
template <class T>
void MsgToString(const T msg, std::string &data) {
    msg.SerializeToString(&data);
}

// 将string转换成msg
template <class T>
void StringToMsg(const std::string data, T &msg) {
    msg.ParseFromString(data);
}
----------------------------------------------------------------------------------------
用法2:

当我们需要使用配置文件来给许多变量进行赋值的时候,就可以把这些变量全都定义在 config.proto中,然后建立一个config.pb.txt文件,在config.pb.txt文件中对config.proto中的变量进行设置。
后续进行一些读取config.pb.txt文件中的内容,然后需要的地方获取这些内容。
代码涉及到文件读取解析proto等等的内容,详解见下:

/**下面这函数是读取配置文件,然后将值赋给message,然后就可以对message以message.mutable_xxx()的形式进行获取数据了**/
/**env_fusion_data_是proto消息,继承于 google::protobuf::Message类**/
pinecone::common::GetProtoFromFile(data_file_name, &message); 

/**定义见下**/
bool GetProtoFromFile(const std::string &file_name,
                      google::protobuf::Message *message) {
  // Try the binary parser first if it's much likely a binary proto.
  static const std::string kBinExt = ".bin";
  if (std::equal(kBinExt.rbegin(), kBinExt.rend(), file_name.rbegin())) {
    return GetProtoFromBinaryFile(file_name, message) ||
           GetProtoFromASCIIFile(file_name, message);
  }

  return GetProtoFromASCIIFile(file_name, message) ||
         GetProtoFromBinaryFile(file_name, message);
}
上面这个函数调用下面这两个函数:
函数1: 读取二进制文件,调用了proto定义的内置函数 bool ParseFromIstream(istream* input)
bool GetProtoFromBinaryFile(const std::string &file_name,
                            google::protobuf::Message *message) {
  std::fstream input(file_name, std::ios::in | std::ios::binary);
  if (!input.good()) {
    SERROR << "Failed to open file " << file_name << " in binary mode.";
    return false;
  }
  if (!message->ParseFromIstream(&input)) {
    SERROR << "Failed to parse file " << file_name << " as binary proto.";
    return false;
  }
  return true;
}
函数2: 读取ASCII文件,调用了open(),close()和proto内置函数static bool Parse(io::ZeroCopyInputStream* input, Message* output);
bool GetProtoFromASCIIFile(const std::string &file_name,
                           google::protobuf::Message *message) {
  using google::protobuf::TextFormat;
  using google::protobuf::io::FileInputStream;
  using google::protobuf::io::ZeroCopyInputStream;
  int file_descriptor = open(file_name.c_str(), O_RDONLY);
  if (file_descriptor < 0) {
    SERROR << "Failed to open file " << file_name << " in text mode.";
    // Failed to open;
    return false;
  }

  ZeroCopyInputStream *input = new FileInputStream(file_descriptor);
  bool success = TextFormat::Parse(input, message);
  if (!success) {
    SERROR << "Failed to parse file " << file_name << " as text proto.";
  }
  delete input;
  close(file_descriptor);
  return success;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【c++】14.编译proto和proto相关用法 的相关文章

  • 如何将 std::string& 转换为 C# 引用字符串

    我正在尝试将 C 函数转换为std string参考C 我的 API 如下所示 void GetStringDemo std string str 理想情况下 我希望在 C 中看到类似的东西 void GetStringDemoWrap r
  • 在模板类中声明模板友元类时出现编译器错误

    我一直在尝试实现我自己的链表类以用于教学目的 我在迭代器声明中指定了 List 类作为友元 但它似乎无法编译 这些是我使用过的 3 个类的接口 Node h define null Node
  • 调用 McAfee 病毒扫描引擎

    我收到客户的请求 要求使用他们服务器上的 McAfee 病毒扫描将病毒扫描集成到应用程序中 我做了一些调查 发现 McScan32 dll 是主要的扫描引擎 它导出各种看起来有用的函数 我还发现提到了 McAfee Scan Engine
  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • 没有特殊字符的密码验证器

    我是 RegEx 的新手 已经进行了大量搜索 但没有找到任何具体内容 我正在编写一个验证密码字符串的正则表达式 可接受的字符串必须至少具有 4 种字符类型中的 3 种 数字 小写字母 大写字母 特殊字符 我对包含有一个想法 也就是说 如果这
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • 如何连接重叠的圆圈?

    我想在视觉上连接两个重叠的圆圈 以便 becomes 我已经有部分圆的方法 但现在我需要知道每个圆的重叠角度有多大 但我不知道该怎么做 有人有主意吗 Phi ArcTan Sqrt 4 R 2 d 2 d HTH Edit 对于两个不同的半
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 在 Unity 中实现 Fur with Shells 技术

    我正在尝试在 Unity 中实现皮毛贝壳技术 http developer download nvidia com SDK 10 5 direct3d Source Fur doc FurShellsAndFins pdf Fins 技术被
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • DotNetZip:如何提取文件,但忽略zip文件中的路径?

    尝试将文件提取到给定文件夹 忽略 zip 文件中的路径 但似乎没有办法 考虑到其中实现的所有其他好东西 这似乎是一个相当基本的要求 我缺少什么 代码是 using Ionic Zip ZipFile zf Ionic Zip ZipFile
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐

  • 理解React的虚拟DOM

    一 背景 React是一个用于构建用户界面的JavaScript库 区别于老的前端开发技术 其最核心的就是引入了虚拟DOM的技术 为了对React有一个比较全面和深入的了解 所以把最近学习React虚拟DOM的知识 做个笔记 仅供学习 二
  • LRU LFU 概念、底层原理及其实现 超详细~

    0 前置提要 本篇约为8650字 阅读完需要约40 60分钟 主要介绍页面置换算法 LRU和LFU的原理及其实现 对应leetcode140和460 如果能给个赞就更好了 1 从内存置换算法说起 计算机的运行的程序和数据保存在内存中 内存的
  • C++ MYSQL 多线程并发查询处理数据

    1 ThreadPool hpp pragma once ifndef THREAD POOL H define THREAD POOL H include
  • ERROR: Could not find a version that satisfies the requirement keras-nightly (from versions: none)

    问题描述 这个错误发生于博主在python 3 8的环境里安装tensorflow 2 5 0时 执行pip install tensorflow 2 5 0 出现了以下错误 ERROR Could not find a version t
  • Java正则表达式详解

    1 1 正则表达式的概念以及演示 正则表达式可以用一些规定的字符来制定规则 并用来校验数据格式的合法性 正则表达式就是用来验证各种字符串的规则 它内部描述了一些规则 我们可以验证用户输入的字符串是否匹配这个规则 正则表达式是一种强大的校验机
  • 2023-8-23 堆排序

    题目链接 堆排序 include
  • python写程序计算无穷级数_[python][计算方法]利用无穷级数计算幂运算(开根号)...

    encoding gbk a的n次方函数 def exp a n ret 1 for i in range 0 n ret a return float ret n n 1 n 2 def getN minus n n x ret floa
  • 【教程】加速访问和下载github项目,原来替换一个域名就可以加速了

    目录 前言 gitee方法 更简便方法 使用教程 前言 大家平时下载github项目的时候 非常的慢 有时候浏览某个项目的md介绍时候 图片就是加载不出来 让人很苦恼 想锤电脑 gitee方法 于是有很多人都是用gitee的方法 先导入到g
  • 【存储管理】brk()系统调用

    尽管应用程序编程时很少直接调用brk 系统调用 但是它是最经常使用的系统调用 1 C语言中的malloc以及C 语言中的new都在间接的调用着brk 这个系统调用 内核中含有3GB的用户虚存空间 会部分映射到物理存储空间 用户程序经过编译
  • vue中怎么引入element以及使用的详细教程

    引入element 安装依赖 在使用 Element 之前 需要先安装 Element 的依赖库 可以使用 npm 或者 yarn 安装 npm npm i element ui S yarn yarn add element ui 引入C
  • Qt 如何关闭 Debug信息输出

    在pro文件中加上DEFINES QT NO DEBUG OUTPUT 然后重新构建一下程序 qDebug的信息就不再输出了 不过qWarning qCritical等信息仍然可以输出 类似的宏还有 QT NO INFO OUTPUT QT
  • 剑指Offer第五十八题:对称的二叉树

    题目描述 请实现一个函数 用来判断一颗二叉树是不是对称的 注意 如果一个二叉树同此二叉树的镜像是同样的 定义其为对称的 1 思路 我们通常有三种不同的二叉树遍历算法 即前序遍历 中序遍历和后序遍历 在这三种遍历算法中 都是先遍历左子结点再遍
  • 良许Linux

    Linux 服务器我们天天打交道 特别是 Linux 工程师更是如此 为了保证服务器的安全与性能 我们经常需要监控服务器的一些状态 以保证工作能顺利开展 本文介绍的几个命令 不仅仅适用于服务器监控 也适用于我们日常情况下的开发 1 watc
  • depcheck检测缺失哪些依赖包

    npm install g depcheck 如果不想全局安装 npm i depcheck后可以在package json的scripts中输入 check depcheck 之后使用 npm run check depcheck npm
  • umi-request 网络请求之路

    umi request 网络请求之路 背景 在做中台业务应用开发的过程中 我们发现在请求链路上存在以下问题 请求库各式各样 没有统一 每次新起应用都需要重复实现一套请求层逻辑 切换应用时需要重新学习请求库 API 各应用接口设计不一致 混乱
  • sql注入Less11-20

    Less 11 POST 1 先登录 在表格中输入admin admin 登录成功后为下图 2 在post data中输入以下 uname passwd 1 submit submit 返回的结果显示存在sql语法错误 证明存在注入漏洞 u
  • 修改别人代码的原则

    工作过程中难免会涉及到修改或维护别人写的代码 如 代码原作者请假 离职 或相关的bug落到了你的头上 或用别人写的通用方法不爽时 如果碰到修改别人的代码时 需要注意哪些事项呢 1 和原作者沟通 当用到了他人写的通用方法 又感觉不爽时 如果原
  • 各个版本chrome允许加载使用flash的方法

    根除办法 在html中嵌入标签 用户自动选择是否加载flash 69 0 之前的版本 1 打开 chrome settings content flash 2 禁止网站运行Flash gt 改为 Ask Default 3 允许 gt 添加
  • golang开发的准备 - gvm(go版本管理软件)的安装

    0 系统环境 ubuntu18 04 1 前置条件 sudo apt get install bison 2 安装步骤 1 从github下载安装包文件 git clone https github com moovweb gvm git
  • 【c++】14.编译proto和proto相关用法

    编译proto和proto相关用法 关于proto相关的知识可以参考系列博客 https blog csdn net daaikuaichuan category 9869251 html xx proto文件中如果要注释的话 注释符号也是