protobuf(C++)的使用(windows)
注:这里说的是C++版本的使用。
1.前言
官网:https://github.com/protocolbuffers/protobuf/releases
protobuf托管在github,在windows上使用需要自己编译,编译需要借助cmake。大概流程是:
a.下载源码-->b.cmake生成vs工程-->c.vs编译(所需lib文件和protoc.exe)-->d.自己的.proto文件生成对应的.h和.cc文件-->e.引入自己的工程使用
还有注意vs的版本和protobuf的版本,编译不成功,大概率是版本的问题。
2.准备(下载源码和工具)
(1)protobuf
最新到3.8.0版了,下载的时候,在该版本的最下面有个“尖”号(Assets),展开就看到了:
说明一下:我要使用protobuf的工程是vs2013,我下载的是3.2.0版本。也试过3.7.1版本用cmake生成失败了,下面再说。
(2)cmake
官网:https://cmake.org/download/
官网下载太慢了,还不如到网上随便找一个。
3.生成vs工程
打开cmake:
选择protobuf下的cmake路径为源码路径,新建文件夹protobuf_win为生成路径。
点击Configure弹出选择vs版本的对话框,(我选vs2013生成成功了)
4.编译protobuf
打开vs工程:
分别编译 libprotobuf和protoc这两个项目:
已debug为例,生成一下文件:libprotobufd.lib、libprotocd.lib和protoc.exe
5.生成***.cc和****.h文件
protobuf使用需要先把消息定义好,然后编译成自己的API,加入到自己的工程中使用。
(1)先编写myproto.proto文件: https://www.ibm.com/developerworks/cn/linux/l-cn-gpb/
syntax = "proto2";
package mypb;
message helloworld
{
required int32 id = 1;
required string str = 2;
optional int32 opt=3;
}
package 名字叫做 mypb,定义了一个消息 helloworld,该消息有三个成员,类型为 int32 的 id,另一个为类型为 string 的成员 str。opt 是一个可选的成员,即消息中可以不包含该成员。
(2)编译myproto.proto文件:
可以使用dos窗口,进入到当前目录,执行:
--cpp_out是输出路径(./为当前路径),其他选项可以使用protoc --help查看
生成文件如下:
6.使用例子
新建工程protobuf,将libprotobufd.lib、libprotocd.lib进入自己的工程,注意这是静态编译的库(也可以在cmake的时候选择动态编译),所以在本工程需要选择静态
另外需要将3.2.0版本(根据自己编译的版本)的源码下的google文件夹引入到自己的工程,在myproto.pb.h中会找这些文件。
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include "myproto.pb.h"
int main(void)
{
//消息封装
mypb::helloworld in_msg;
{
in_msg.set_id(888);
in_msg.set_str("helloworld");
std::fstream output("./hello.log", std::ios::out | std::ios::trunc | std::ios::binary);
if (!in_msg.SerializeToOstream(&output)) {
std::cerr << "failed to serialize in_msg" << std::endl;
return -1;
}
}
//消息解析
mypb::helloworld out_msg;
{
std::fstream input("./hello.log", std::ios::in | std::ios::binary);
if (!out_msg.ParseFromIstream(&input)) {
std::cerr << "failed to parse" << std::endl;
return -1;
}
std::cout << out_msg.id() << std::endl;
std::cout << out_msg.str() << std::endl;
}
getchar();
return 0;
}
试了一下如果消息里有中文,会报错,但是能解析出来(还没找原因):