Ubuntu16.04 安装protobuf C++

1、Protobuf的安装

1.1依赖环境的安装

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

1.2下载 protobuf源码下载

github源代码下载地址:https://github.com/google/protobuf

1
git clone https://github.com/protocolbuffers/protobuf.git

1.3 进入目录配置autogen/configure

1
cd protobuf
1
2
./autogen.sh
./configure --prefix=/usr/local/protobuf

这个地方如果出现了警告configure: WARNING: no configuration information is in third_party/googletest就需要注意了,这个warning需要解决的,不然后面编译不过

搜索答案发现需要讲googletest下载最新版本 然后放在 thrid/googletest目录下,并且重新命名为googletest(就是删除后面的版本号),tar.gz下载地址:https://github.com/google/googletest/archive/release-1.8.1.tar.gz但是我没有成功,于是尝试一下方法:

如果下载不完整,使用:

1
git submodule update --init --recursive

然后再来一遍:

./autogen.sh
./configure --prefix=/usr/local/protobuf

1.4 编译make

1
make -j4

1.5 make check

1
make check

如果没有报错 那就是成功了,可以安装了

1.6 安装

1
sudo make install

提示:如果安装了两次、最好使用witch查找一下、不然有可能编译的时候各种define找不到

1.7 检测安装是否成功

1
2
~$ protoc --version
libprotoc 2.6.1

2 测试

  proto文件的编写方法就是类似于定义一个class / struct(随便怎么理解)存储需要序列化的数据,再把这个数据序列化进行传输,然后反序列化解读出来。

2.1 编写.proto文件

1
2
3
4
5
6
7
8
message xxx {
  // 字段规则:required -> 字段只能也必须出现 1 次
  // 字段规则:optional -> 字段可出现 0 次或1次
  // 字段规则:repeated -> 字段可出现任意多次(包括 0)
  // 类型:int32、int64、sint32、sint64、string、32-bit ....
  // 字段编号:0 ~ 536870911(除去 19000 到 19999 之间的数字)
  字段规则 类型 名称 = 字段编号;
}

例如:

1
2
3
4
5
6
7
8
//helloworld.proto
package lm;

message People {
    required string str = 1;
    required int32 id = 2;
    optional string email = 3;
}

name 是 required修饰,必须出现一次

id 是required修饰,所以必须出现一次

email是optional修饰,可以出现一次或0次

具体使用看看:官方文档C++

2.2 生成proto的读写借口文件

c++为例:生成的对应文件是xxx.pb.cc 和 xxx.pb.h文件

生成命令:

1
2
3
4
5
6
// $SRC_DIR: .proto 所在的源目录
// --cpp_out: 生成 c++ 代码
// $DST_DIR: 生成代码的目标目录
// xxx.proto: 要针对哪个 proto 文件生成接口代码
 
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/xxx.proto

通过tree来查看目录可以发现结构如下:

1
2
3
4
.
├── helloworld.pb.cc
├── helloworld.pb.h
└── helloworld.proto

2.3编译链接proto的读写文件

这个时候才是重点,之前在这里卡了很久,主要是安装了两次make install两次protobuf,一次是./configure --prefix=/usr/local/protobuf 另一次 ./cpmfigure 导致有两个protobuf本地库被安装,所以链接的时候出问题了,最后百度了一下删除protobuf了重新来就好了,这里贴一下删除protobuf的方法:

1
2
3
4
5
sudo apt-get remove libprotobuf-dev

which protoc找到文件位置,比如是/usr/local/bin/protoc。

执行sudo rm /usr/local/bin/protoc就可以了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// main.cpp
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string>
#include <pthread.h>
#include <fstream>
#include "helloworld.pb.h"

#define BUFFSIZE 1024
using namespace std;

int main()
{
    GOOGLE_PROTOBUF_VERIFY_VERSION;
    lm::helloworld msg1;
    msg1.set_id(1);
    msg1.set_str("test1");
    fstream output("./log", ios::out | ios::trunc | ios::binary);
    if (!msg1.SerializeToOstream(&output)) {
        cerr << "Failed to write msg." << endl;
        return -1;
    }
    output.close();
    cout << msg1.id() << endl;
    cout << msg1.str() << endl;
}

链接方法:

1
g++ helloworld.pb.cc main.cpp -lprotobuf -lpthread -std=c++11

常见错误:undefined reference to`pthread_once' 。解决方法 不要忘记使用-lpthread

常见错误:error: ‘static_assert’ was not declared in this scope。解决方法 -std=c++11

文件目录如下:

1
2
3
4
5
6
.
├── a.out
├── helloworld.pb.cc
├── helloworld.pb.h
├── helloworld.proto
└── main.cpp

运行./a.out