IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 【CMake/Protobuf】CMake 下使用 protobuf -> 正文阅读

[游戏开发]【CMake/Protobuf】CMake 下使用 protobuf

?????????protobuf是google开发的一个序列化和反序列化的库,通过.proto文件定义文件格式,序列化后的数据是binary的,可以在多语言上使用.一般情况下,若客户端和服务端都是自己做的,用protobuf作为通讯协议,无疑是一个不错的选择.

????????protobuf是一种用于对结构数据进行序列化的工具,从而实现数据存储和交换。主要用于网络通信中收发两端进行数据交互。所谓的数据结构是指类似于struct结构体数据,可用于表示一个网络消息。当结构体中存在函数指针类型是,直接对其存储或传输相当于浅拷贝,而对其进行序列化后相当于深拷贝。

????????序列化:将结构体数据或者对象转换成能够用于存储和传输的格式

? ? ? ? 反序列化:在其他进程中,将序列化后的数据还原为数据结构和对象?

个人一般使用CMake来管理c++工程.那么,cmake下使用protobuf对个人而言是个很重要的事情.

cmake有官方的modules,文件是FindProtobuf.cmake,里面有宏PROTOBUF_GENERATE_CPP.用法据介绍如下:

INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS foo.proto)
ADD_EXECUTABLE(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS})
TARGET_LINK_LIBRARIES(bar ${PROTOBUF_LIBRARIES})

以上用法在proto文件均在同意文件夹下或者各proto文件之间无相互引用得情况下可使用,但是存在proto文件不在同意文件夹下且文件之间有相互引用得情况下,使用上述PROTOBUF_GENERATE_CPP宏,此时就会存在编译失败得问题出现,那么针对这种情况该如何处理,如何正确编写cmake解决此类问题呢

网上看的一个proto文件import引用其他proto文件为例子

// mediapipe/framework/calculator.proto
syntax = "proto3";

package mediapipe;

import public "mediapipe/framework/calculator_options.proto";
import "google/protobuf/any.proto";
import "mediapipe/framework/mediapipe_options.proto";
import "mediapipe/framework/packet_factory.proto";
import "mediapipe/framework/packet_generator.proto";
import "mediapipe/framework/status_handler.proto";
import "mediapipe/framework/stream_handler.proto";

每个.proto文件都import了其他目录下的文件,这里的import类似于C++中的include,但是这里的import又可以相互引用,例如上述的status_handler.proto也引用了mediapipe_options.proto。

如果直接对上述所有的.proto文件直接使用protobuf_generate_cpp命令,会直接报错,因为这些文件不在一个目录,而且import的相对目录也无法分析。另外,不同目录内的.cc文件会引用相应目录生成的.pb.h文件,我们需要生成的.pb.cc和.pb.h在原始的目录中,这样才可以正常引用,要不然需要修改其他源代码的include地址,比较麻烦。

正确修改cmake

对于这种情况,比较合适的做法是直接使用命令进行生成。

首先找到所有需要编译的.proto文件:

file(GLOB protobuf_files
????????mediapipe/framework/*.proto
????????mediapipe/framework/tool/*.proto
????????mediapipe/framework/deps/*.proto
????????mediapipe/framework/testdata/*.proto
????????mediapipe/framework/formats/*.proto
????????mediapipe/framework/formats/annotation/*.proto
????????mediapipe/framework/formats/motion/*.proto
????????mediapipe/framework/formats/object_detection/*.proto
????????mediapipe/framework/stream_handler/*.proto
????????mediapipe/util/*.proto
????????mediapipe/calculators/internal/*.proto
????????)

接下来,定义相关的目录地址,PROTO_META_BASE_DIR为编译之后生成文件的目录。PROTO_FLAGS很重要,指定编译.proto文件时的总的寻找路径,.proto中的import命令根据根据这个地址去连接其他的.proto文件

SET(PROTO_META_BASE_DIR ${CMAKE_CURRENT_BINARY_DIR})
LIST(APPEND PROTO_FLAGS -I${CMAKE_CURRENT_SOURCE_DIR})

设置好之后,通过FOREACH去循环之前的.proto文件,依次编译每个文件,然后将生成的.pb.cc和.pb.h移动回原始的目录,至此就可以正常工作了。

FOREACH(FIL ${protobuf_files})
????GET_FILENAME_COMPONENT(FIL_WE ${FIL} NAME_WE)
????string(REGEX REPLACE ".+/(.+)\\..*" "\\1" FILE_NAME ${FIL})
????string(REGEX REPLACE "(.+)\\${FILE_NAME}.*" "\\1" FILE_PATH ${FIL})
????string(REGEX MATCH "(/mediapipe/framework.*|/mediapipe/util.*|/mediapipe/calculators/internal/)" OUT_PATH ${FILE_PATH})

????set(PROTO_SRCS "${CMAKE_CURRENT_BINARY_DIR}${OUT_PATH}${FIL_WE}.pb.cc")
????set(PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR}${OUT_PATH}${FIL_WE}.pb.h")
????EXECUTE_PROCESS(

????????????COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} ${PROTO_FLAGS} --cpp_out=${PROTO_META_BASE_DIR} ${FIL}

????)

????message("Copying " ${PROTO_SRCS} " to " ${FILE_PATH})
????file(COPY ${PROTO_SRCS} DESTINATION ${FILE_PATH})
????file(COPY ${PROTO_HDRS} DESTINATION ${FILE_PATH})
ENDFOREACH()

上述是在网上查看得例子所描述得方法,下面以自己得工程进行实际操作

Cmake编写如下

INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
SET(PROTO_META_BASE_DIR ${CMAKE_CURRENT_BINARY_DIR})
LIST(APPEND PROTO_FLAGS
? ? -I${CMAKE_CURRENT_SOURCE_DIR}/Proto
? ? -I${CMAKE_CURRENT_SOURCE_DIR}/../)
file(GLOB proto_files
? ? ${CMAKE_CURRENT_SOURCE_DIR}/Proto/*.proto
? ? ${CMAKE_CURRENT_SOURCE_DIR}/../A/Proto/*.proto
? ? ${CMAKE_CURRENT_SOURCE_DIR}/../B/Proto/*.proto
)
FOREACH(FIL ${proto_files})
? ? GET_FILENAME_COMPONENT(FIL_WE ${FIL} NAME_WE)
? ? string(REGEX REPLACE ".+/(.+)\\..*" "\\1" FILE_NAME ${FIL})
? ? string(REGEX REPLACE "(.+)\\${FILE_NAME}.*" "\\1" FILE_PATH ${FIL})
? ? string(REGEX MATCH "(/A/Proto/.*|/B/Proto/.*)" OUT_PATH ${FILE_PATH})
? ? EXECUTE_PROCESS(
? ? ? ? ? ? COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} ${PROTO_FLAGS} --cpp_out=${PROTO_META_BASE_DIR} ${FIL}
? ? )
? ? LIST(APPEND TOTAL_PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR}/${OUT_PATH}${FIL_WE}.pb.h")
? ? LIST(APPEND TOTAL_PROTO_SRCS "${CMAKE_CURRENT_BINARY_DIR}/${OUT_PATH}${FIL_WE}.pb.cc")
ENDFOREACH()
add_executable(${BIN_NAME} ${ALL_SRCS} ${TOTAL_PROTO_HDRS} ${TOTAL_PROTO_SRCS})

?编译结果

针对工程proto比较复杂的可以通过上述方法进行使用

对于proto文件比较少,工程不太复杂的可以使用PROTOBUF_IMPORT_DIRS即可

:【Cmake/Protobuf】PROTOBUF_IMPORT_DIRS的使用_无名 小卒的博客-CSDN博客

cmake之string命令解析:cmake之string命令解析_kernelplus的博客-CSDN博客_cmake中string

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:49:29  更:2022-04-09 18:53:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/16 21:08:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码