Protobuf的簡單使用

1、說明

本文主要介紹 Protobuf 庫的在C++中的使用方式

平台:ubuntu 18.04

語言:C++

構建工具:cmake

2、Protobuf編譯安裝

github 下載所需要的 Protobuf 程式碼,本次下載:protobuf-cpp-3.21.3.tar.gz

解壓後編譯:

mkdir build && cd build
cmake ..
make -j6
sudo make install
sudo ldconfig

驗證安裝:

protoc --version #列印版本號
libprotoc 3.21.3

3、cmake中使用

Protobuf 的使用方式很多,可以自行手動生成程式碼,也可以使用cmake自動生成

3.1、手動生成程式碼的方式

以下程式碼的目錄結構為:

.
├── CMakeLists.txt
├── include 		#空文件夾,方便存儲生成的程式碼
├── main.cpp
└── message
    └── test.proto

創建 cmake 項目,創建 proto 文件

//文件:test.proto
//這裡的package生成程式碼後,在c++中是命名空間
package test;
message TestOne { //TestOne是類名
	required string name = 1;
	optional int32 age = 2;
}

使用protoc生成程式碼:

# protoc proto文件 -cpp_out=指定生成的程式碼路徑
# --cpp_out表示生成C++程式碼,也可以制定多個不同語言
protoc message/test.proto --cpp_out=./include/

以上指令運行之後,則在 include 目錄下生成 C++ 程式碼(.h 和 .cc)

目錄結構是:

.
├── CMakeLists.txt
├── include
│   └── message #目錄層級和proto相同
│       ├── test.pb.cc #實現文件
│       └── test.pb.h  #頭文件
├── main.cpp
└── message
    └── test.proto

項目中使用:

因為程式碼是手動生成的,所以 CMakeLists.txt 需要像自己寫程式碼一樣,把程式碼加入到項目中,如下:

cmake_minimum_required(VERSION 3.10)
project(protobuf_test)

set(CMAKE_CXX_STANDARD 11)

# 生成的程式碼中還需要使用到protobuf包
find_package(Protobuf REQUIRED)

include_directories(./include)
include_directories(./include/message)

#生成的的程式碼需要手動加入
add_executable(protobuf_test 
	main.cpp 
	include/message/test.pb.cc 
	include/message/test.pb.h
)
#因為生成的程式碼中還用到protobuf,所以還需要鏈接庫
target_link_libraries(protobuf_test
    ${PROTOBUF_LIBRARIES}
)

程式碼如下:

#include <iostream>
#include <test.pb.h>
using namespace std;
int main()
{
    test::TestOne testOne;
    testOne.set_name("sherlock");
    testOne.set_age(100);

    cout << testOne.name() << endl;
    cout << testOne.age() << endl;
    return 0;
}

編譯運行OK

3.2、cmake自動生成程式碼方式

3.1中使用指令生成程式碼是最基礎的使用,但是一般項目中,大面積的使用,proto文件也會經常刪減,自動化集成也不可能運行手動構建,因此支援自動構建是必然

CMakeLists.txt 文件修改如下:

cmake_minimum_required(VERSION 3.10)
project(protobuf_test)

set(CMAKE_CXX_STANDARD 11)
#protobuf包仍然是必須的
find_package(Protobuf REQUIRED)

include_directories(./include)

#主要是這句,使用protoc生成文件
PROTOBUF_GENERATE_CPP(SRCS HDRS message/test.proto)

add_executable(protobuf_test main.cpp ${PROTO_SRCS} ${PROTO_HDRS})

target_include_directories(protobuf_test
    PUBLIC
    ${PROTOBUF_INCLUDE_DIRS}
    ${CMAKE_CURRENT_BINARY_DIR}
)
target_link_libraries(protobuf_test
    ${PROTOBUF_LIBRARIES}
)

PROTOBUF_GENERATE_CPP 宏可以生成程式碼文件,並返回程式碼,第一個和第二個參數是傳出值,分別表示生成的cpp文件和頭文件,第三個參數指定 proto 文件,但是不能指定生成路徑,生成的文件在編譯根目錄下

main.cpp 文件不變,編譯運行即可