Protocol Buffers(简称:ProtoBuf)是一种开源跨平台的序列化数据结构的协议。其对于存储资料或在网络上进行通信的程序是很有用的。这个方法包含一个接口描述语言,描述一些数据结构,并提供程序工具根据这些描述产生代码,这些代码将用来生成或解析代表这些数据结构的字节流。

protobuf主要解决了将对象型数据(基于OOP设计协议更易于理解)序列化成为一种字节流数据格式,至于数据最终被如何使用,需要设计者考虑。例如用于存储,传输。

准备工作

安装CMake

  • 下载Cmake 官方下载地址
  • image-1688895998998
  • 下载完成自己安装就行,安装完成会带两个程序,应该是无GUI的CMake,我们这里使用CmakeGUI

下载Protobuf源码

git clone git@github.com:protocolbuffers/protobuf.git

cd protobuf
git submodule update --init --recursive

使用CMake生成编译环境

  • image-1688896465426
  • 第一个就是源码路径
  • 第二个就是要生成的目录,然后点击左下角的Configure
  • image-1688896513608
  • 第一个是生成什么项目,我是2019的,第二个是什么平台,默认X64,然后点击Finish
  • 如果出现错误那就是你没有安装依赖,子模块什么的,别看上面的红色,要看下面输出的信息有没有错误
  • image-1688896559968
  • 构建后是这样的,然后点击左下角Generate 这会生成工程文件

VS中编译Protobuf项目

  • 打开你生成的项目protobuf.sln
  • 将平台设置为Release x64
  • image-1688896781046
  • 选中红框里的2个项目,右击,设置运行库为 多线程DLL (/MD) 应用确定
  • 然后直接选中ALL_BUILD 右击重新生成
  • image-1688897165231
  • 编译完成后,找到编译的文件
  • image-1688897384887
  • 主要需要这几个文件

虚幻引擎引入

  • 在你的项目源码文件夹Source下边添加ThirdParty文件夹,用于导入第三方Protobuf库
  • 在下边在创建一个文件夹,例如Protobuf
  • image-1688897512161
  • 在Protobuf文件夹下新建3个文件夹,bin include lib
  • 下面再新建Win64文件夹,因为我们编译的是win平台64的依赖
  • image-1688897583913
  • 把生成的protoc.exe放入bin文件夹,libprotobuf.lib和libprotoc.lib放入lib文件夹
  • 然后找到你的protobuf的源码文件夹下有一个src文件夹image-1688897803844
  • 复制google文件夹到你的include文件夹
  • 删除compiler,testdata,testing这几个没用的文件夹,下面的.proto文件也删了
  • image-1688897875706
  • 文件结构
  • image-1688898341863

配置Build.cs

  • 找到你的xxxx.Build.cs
  • 写入,注意,ThridPartyPath这个是我自己配置好的路径变量,这个你需要自己配置
  • 相当于
Path.Combine(ModuleDirectory, "../ThridParty/")
  • 记得引入System
using System;
using System.IO;
  • 然后添加以下代码

 if (Target.Platform == UnrealTargetPlatform.Win64)
        {
              PublicAdditionalLibraries.Add(Path.Combine(ThridPartyPath, "Protobuf", "lib", "Win64", "libprotobuf.lib"));
              PublicAdditionalLibraries.Add(Path.Combine(ThridPartyPath, "Protobuf", "lib", "Win64", "libprotoc.lib"));
              PublicSystemLibraries.Add(Path.Combine(ThridPartyPath, "Protobuf", "lib", "Win64", "libprotobuf.lib"));
              PublicSystemLibraries.Add(Path.Combine(ThridPartyPath, "Protobuf", "lib", "Win64", "libprotoc.lib"));
		}
        
        
        PublicIncludePaths.AddRange(new string[] {Path.Combine(ThridPartyPath, "Protobuf/include")});
           
           
         if (Target.Platform == UnrealTargetPlatform.Win64)
        {
            PublicAdditionalLibraries.Add(Path.Combine(ThridPartyPath, "Protobuf", "lib", "Win64", "libprotobuf.lib"));
            PublicAdditionalLibraries.Add(Path.Combine(ThridPartyPath, "Protobuf", "lib", "Win64", "libprotoc.lib"));
            PublicSystemLibraries.Add(Path.Combine(ThridPartyPath, "Protobuf", "lib", "Win64", "libprotobuf.lib"));
            PublicSystemLibraries.Add(Path.Combine(ThridPartyPath, "Protobuf", "lib", "Win64", "libprotoc.lib"));
		}
        
            PublicDefinitions.Add("GOOGLE_PROTOBUF_NO_RTTI=1");

        ShadowVariableWarningLevel = WarningLevel.Off;
        bEnableUndefinedIdentifierWarnings = false;
        if (Target.Platform == UnrealTargetPlatform.Win64)
        {
            bEnableExceptions = true;
		}
        
          PublicDefinitions.Add("_CRT_SECURE_NO_WARNINGS");
  • 然后找到你的项目.uproject右击,Generate …
  • image-1688898969162

在引擎中使用Protobuf

  • 如果你是作为模块使用,那你需要在build文件里添加引用
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UEProtobuf" });
  • 如果你是封装的插件,那就无视
  • 然后你需要有一个xxxxx.proto文件 ,找到先前生成的protoc.exe
  • 打开cmd,cd到这个目录,执行cmd命令
protoc xxxx.proto --cpp_out=./
  • 如果你的proto文件没问题,你会得到一个** xxx.pb.cc** 和 xxx.pb.h 文件
  • 将 .cc 文件放入你源码中的Private文件夹,.h文件放入Public
  • 此时编译肯定是不通过的,所以我们要屏蔽掉一些警告
  • 打开.cc和.h这两个文件,在第一行添加如下代码屏蔽警告
#ifdef _MSC_VER
#pragma warning(disable: 4946)
#pragma warning(disable: 4125)
#pragma warning(disable: 4647)
#pragma warning(disable: 4668)
#pragma warning(disable: 4800)
#endif

然后在你的cpp里添加引用

#include "xxxx.pb.h"
  • 你就可以使用了
  • 如果编译时出现下列错误
  inlined_string_field.h(430): [C4668] 没有将“GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE”定义为预处理器宏,用“0”替换“#if/#elif”
  inlined_string_field.h(430): [C4668] 没有将“GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE”定义为预处理器宏,用“0”替换“#if/#elif”
  Microsoft.MakeFile.targets(45, 5): [MSB3073] 命令“"D:\Program Files\Epic Games\UE_5.1\Engine\Build\BatchFiles\Build.bat" ProtobufToturialEditor Win64 Development -Project="D:\Projectes\UE\ProtobufToturial\ProtobufToturial.uproject" -WaitMutex -FromMsBuild”已退出,代码为 6。


  • 这个错误是因为需要在项目中配置预处理宏,用来管理是启用调试和非调试。修改方法如下:
  • 到inlined_string_field.h文件中(双击错误跳转),将代码进行修改,参照如下:
#if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
  lhs->get_mutable()->swap(*rhs->get_mutable());
  if (!lhs_arena_dtor_registered && rhs_arena_dtor_registered) {
    lhs_msg->OnDemandRegisterArenaDtor(lhs_arena);
  } else if (lhs_arena_dtor_registered && !rhs_arena_dtor_registered) {
    rhs_msg->OnDemandRegisterArenaDtor(rhs_arena);
  }


  • 修改后

//调整此段
#ifdef GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
  lhs->get_mutable()->swap(*rhs->get_mutable());
  if (!lhs_arena_dtor_registered && rhs_arena_dtor_registered) {
    lhs_msg->OnDemandRegisterArenaDtor(lhs_arena);
  } else if (lhs_arena_dtor_registered && !rhs_arena_dtor_registered) {
    rhs_msg->OnDemandRegisterArenaDtor(rhs_arena);
  }


  • 再次编译即可通过

到此将protobuf引入虚幻引擎5.1.1 结束