Protobuf的簡單使用

2022-07-26 06:01:14

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 檔案不變,編譯執行即可