Linux环境下Clion整合Protobuf小结

一、安装Protobuf环境

#安装依赖项目
sudo apt-get install autoconf automake libtool curl make g++ unzip
#下载最新源码
git clone https://github.com/google/protobuf.git
#进入目录
cd protobuf
#更新源
git submodule update --init --recursive
#生成依赖项目
./autogen.sh
#配置
./configure
#编译
make
#编译确认
make check
#安装
sudo make install
 # refresh shared library cache(刷新共享库配置)
sudo ldconfig
#查看版本
protoc --version

二、工程整合

1. 新建***.proto文件

proto文件
/*****PbTest.proto******/

syntax = "proto3";   //设定proto版本,不同版本语法不一样

package tutorial;

message Person {
  string name = 1;
  int32 id = 2;   //整型
  string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {  //定义类,也可以另起到外部message
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;  //关键字repeated代表不定长链表,对标list类
}

message AddressBook {
   Person people = 1;  //类嵌套
}

2. 开始转换

  • 进入proto文件所在目录执行:protoc --cpp_out=. PbTest.proto

语法: protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/XXXX.proto
案例: protoc --cpp_out=. XXXX.proto

  • 会在当前目录生成两个文件,如下图:
    生成***.cc和***.h文件

3. 文件加入工程

加入工程目录
  • 配置makelist文件:
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

...

include(FindProtobuf)
find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIR})

target_link_libraries(
        ${PROTOBUF_LIBRARY}
)

4. 编译运行

  • 代码中引用:
    TuneParamsModel para;
    para.set_cad(5);

    /******************Stream***********************/
    // fstream out("out.txt", ios::out | ios::trunc);
    ofstream out("out.txt", ios::out | ios::trunc);
    para.SerializeToOstream(&out);
    out.close();
    TuneParamsModel ret;
    ifstream src ("out.txt", ios::in);
    ret.ParsePartialFromIstream(&src);
    src.close();
    /*******************Array***********************/
    size_t len =  para.ByteSizeLong();
    char buf[len];
    para.SerializeToArray( buf,len);

    TuneParamsModel ret;
    ifstream src ("out.txt");
    if (! src.is_open())
    { cout << "Error opening file"; exit (1); }
    while (! src.eof() ) {
        src.read (buf, len);
    }
    ret.ParseFromArray(buf, len);

    printf("Value Compare Result: %d", ret.cad() == para.cad());
    /*******************File***********************/
    TuneParamsModel _ret;
    ifstream _src ("protoBufferTest", ios::in);
    _ret.ParsePartialFromIstream(&_src);
    _src.close();
  • 编译并执行:
    enjoy it...

三、常见故障处理

1. 提示如下错误:

CMakeFiles/MedianMachine.dir/frame/MyProto.pb.cc.o: In function InitDefaultsscc_info_MyProto_MyProto_2eproto()': /media/chj/Code/MassHunter/MedianMachine/frame/MyProto.pb.cc:29: undefined reference togoogle::protobuf::internal::VerifyVersion(int, int, char const)'
CMakeFiles/MedianMachine.dir/frame/MyProto.pb.cc.o: In function InitDefaultsscc_info_MyType_MyProto_2eproto()': /media/chj/Code/MassHunter/MedianMachine/frame/MyProto.pb.cc:47: undefined reference togoogle::protobuf::internal::VerifyVersion(int, int, char const
)'
CMakeFiles/MedianMachine.dir/frame/MyProto.pb.cc.o: In function test::MyProto_MessageType_descriptor()': /media/chj/Code/MassHunter/MedianMachine/frame/MyProto.pb.cc:123: undefined reference togoogle::protobuf::internal::AssignDescriptors(google::protobuf::internal::DescriptorTable const, bool)'
CMakeFiles/MedianMachine.dir/frame/MyProto.pb.cc.o: In function test::MyType::_InternalParse(char const*, google::protobuf::internal::ParseContext*)': /media/chj/Code/MassHunter/MedianMachine/frame/MyProto.pb.cc:231: undefined reference togoogle::protobuf::internal::UnknownFieldParse(unsigned long, google::protobuf::UnknownFieldSet
, char const, google::protobuf::internal::ParseContext)'
CMakeFiles/MedianMachine.dir/frame/MyProto.pb.cc.o: In function `test::MyType::_InternalSerialize(unsigned char, google::protobuf::io::EpsCopyOutputStream) const':

...

CMakeFiles/MedianMachine.dir/frame/MyProto.pb.cc.o:(.data.rel.ro._ZTIN4test6MyTypeE[_ZTIN4test6MyTypeE]+0x10): undefined reference to `typeinfo for google::protobuf::Message'
collect2: error: ld returned 1 exit status
CMakeFiles/MedianMachine.dir/build.make:233: recipe for target 'MedianMachine' failed
make[3]: *** [MedianMachine] Error 1
CMakeFiles/Makefile2:75: recipe for target 'CMakeFiles/MedianMachine.dir/all' failed
make[2]: *** [CMakeFiles/MedianMachine.dir/all] Error 2
CMakeFiles/Makefile2:82: recipe for target 'CMakeFiles/MedianMachine.dir/rule' failed
make[1]: *** [CMakeFiles/MedianMachine.dir/rule] Error 2
Makefile:118: recipe for target 'MedianMachine' failed
make: *** [MedianMachine] Error 2

  • 原因分析:工程配置原因

  • 处理方法:编辑makelist文件,添加如下项目:

include(FindProtobuf)
find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIR})

...

target_link_libraries(

...

    ${PROTOBUF_LIBRARY}
)

2. 定制化编译与安装

  • protobuf 默认安装在 /usr/local 目录

  • 你可以通过 ./configure --prefix=路径 指令修改安装目录

  • 为了避免安装乱象,可以安装在/usr/local/protobuf目录下

./configure --prefix=/usr/local/protobuf
make
make check
make install
  • 到此步还没有完成,在/etc/profile 或者用户目录 ~/.bash_profile 添加下面内容:
####### add protobuf lib path ########
#(动态库搜索路径) 程序加载运行期间查找动态链接库时指定除了系统默认路径之外的其他路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/protobuf/lib/
#(静态库搜索路径) 程序编译期间查找动态链接库时指定查找共享库的路径
export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/protobuf/lib/
#执行程序搜索路径
export PATH=$PATH:/usr/local/protobuf/bin/
#c程序头文件搜索路径
export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/local/protobuf/include/
#c++程序头文件搜索路径
export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/usr/local/protobuf/include/
#pkg-config 路径
export PKG_CONFIG_PATH=/usr/local/protobuf/lib/pkgconfig/
######################################
  • 如果出现找不到符号和链接错误请记得加上链接选项 -lprotobuf, 并确认你的静态库路径是否生效了 echo $LIBRARY_PATH`

3. 版本升级

  • 卸载之前版本:
sudo apt-get --purge remove libprotobuf-dev
sudo apt-get --purge remove protobuf-compiler
  • 重新编译安装新版本,步骤同《定制化编译与安装》

  • 期间如果出现:
    E: Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)

  • 原因:
    非正常停止apt-get install *

  • 解决方法:

sudo apt-get --fix-broken install

4.交叉编译

  • 编译定制化指令格式:

./configure --host=<HOST_NAME> CC=<YOUR_COMPILER_PATH>/<COMPILER_GCC> CXX=<YOUR_COMPILER_PATH>/<COMPILER_G++> --disable-protoc --prefix=<TARGET_INSTALL_PATH>

  • 例如:
# aarch64-linux-gnu平台
./configure --host=aarch64-linux-gnu CC=/usr/local/gcc-arm-x86_64-aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc CXX=/usr/local/gcc-arm-x86_64-aarch64-linux-gnu/bin/aarch64-linux-gnu-g++ --disable-protoc --prefix=/usr/local/protobuf-aarch64-linux-gnu
# arm-none-linux-gnueabihf 平台
./configure --host=arm-none-linux-gnueabihf CC=/usr/local/gcc-arm-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-gcc CXX=/usr/local/gcc-arm-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-g++ --disable-protoc --prefix=/usr/local/protobuf-arm-none-linux-gnueabihf
# 32位arm-linux-gnueabi平台
./configure --host=arm-linux-gnueabi CC=/usr/local/gcc-linaro-arm-linux-gnueabihf-4.7/bin/arm-linux-gnueabihf-gcc CXX=/usr/local/gcc-linaro-arm-linux-gnueabihf-4.7/bin/arm-linux-gnueabihf-g++ --disable-protoc --prefix=/usr/local/protobuf-arm-linux-gnueabi
  • 重复《定制化编译与安装》的步骤
  • 编辑工程 MakeList.txt 文件
#  host: arm-none-linux-gnueabihf 
# protobuf 路径配置
SET(PROTOBUF_FOUND                /usr/local/protobuf-arm-none-linux-gnueabihf/)
# protobuf 库路径配置
SET(PROTOBUF_LIBRARY              /usr/local/protobuf-arm-none-linux-gnueabihf/lib/libprotobuf.so)
# protobuf 头文件配置
SET(PROTOBUF_INCLUDE_DIR          /usr/local/protobuf-arm-none-linux-gnueabihf/include/)
# protobuf 执行文件配置
SET(PROTOBUF_PROTOC_EXECUTABLE    /usr/local/protobuf-arm-none-linux-gnueabihf/bin/protoc)

# host: aarch64-linux-gnu
SET(PROTOBUF_FOUND                /usr/local/protobuf-aarch64-linux-gnu/)
SET(PROTOBUF_LIBRARY              /usr/local/protobuf-aarch64-linux-gnu/lib/libprotobuf.so)
SET(PROTOBUF_INCLUDE_DIR          /usr/local/protobuf-aarch64-linux-gnu/include/)
SET(PROTOBUF_PROTOC_EXECUTABLE    /usr/local/protobuf-aarch64-linux-gnu/bin/protoc)

5. protobuf 系统帮助

  • 输入指令:
cmake --help-module FindProtobuf

Locate and configure the Google Protocol Buffers library.

The following variables can be set and are optional:

PROTOBUF_SRC_ROOT_FOLDER
When compiling with MSVC, if this cache variable is set
the protobuf-default VS project build locations
(vsprojects/Debug and vsprojects/Release
or vsprojects/x64/Debug and vsprojects/x64/Release)
will be searched for libraries and binaries.
PROTOBUF_IMPORT_DIRS
List of additional directories to be searched for
imported .proto files.

Defines the following variables:

PROTOBUF_FOUND
Found the Google Protocol Buffers library
(libprotobuf & header files)
PROTOBUF_INCLUDE_DIRS
Include directories for Google Protocol Buffers
PROTOBUF_LIBRARIES
The protobuf libraries
PROTOBUF_PROTOC_LIBRARIES
The protoc libraries
PROTOBUF_LITE_LIBRARIES
The protobuf-lite libraries

The following cache variables are also available to set or use:

PROTOBUF_LIBRARY
The protobuf library
PROTOBUF_PROTOC_LIBRARY
The protoc library
PROTOBUF_INCLUDE_DIR
The include directory for protocol buffers
PROTOBUF_PROTOC_EXECUTABLE
The protoc compiler
PROTOBUF_LIBRARY_DEBUG
The protobuf library (debug)
PROTOBUF_PROTOC_LIBRARY_DEBUG
The protoc library (debug)
PROTOBUF_LITE_LIBRARY
The protobuf lite library
PROTOBUF_LITE_LIBRARY_DEBUG
The protobuf lite library (debug)

Example:

find_package(Protobuf REQUIRED)
include_directories({PROTOBUF_INCLUDE_DIRS}) include_directories({CMAKE_CURRENT_BINARY_DIR})
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS foo.proto)
protobuf_generate_python(PROTO_PY foo.proto)
add_executable(bar bar.cc {PROTO_SRCS}{PROTO_HDRS})
target_link_libraries(bar ${PROTOBUF_LIBRARIES})

.. note::
The protobuf_generate_cpp and protobuf_generate_python
functions and add_executable() or add_library()
calls only work properly within the same directory.

.. command:: protobuf_generate_cpp

Add custom commands to process .proto files to C++::

protobuf_generate_cpp (<SRCS> <HDRS> [<ARGN>...])

SRCS
Variable to define with autogenerated source files
HDRS
Variable to define with autogenerated header files
ARGN
.proto files

.. command:: protobuf_generate_python

Add custom commands to process .proto files to Python::

protobuf_generate_python (<PY> [<ARGN>...])

PY
Variable to define with autogenerated Python files
ARGN
.proto filess

6. C语言兼容

# 执行指令:
./configure && make && make install
# 或者执行指令:
./autogen.sh && ./configure && make && make install
  • 生成C文件和头文件
protoc --c_out=. example.proto

参考文献:


C语言使用Demo
MakeList文件故障处理
文件流处理
纯C语言实现方案
应用案例
交叉编译protobuf
入门手册
类型说明
参考手册
常用序列化函数
C语言使用案例
C语言源码仓库

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342