前言

在编译完成Protobuf项目后(如何编译Protobuf项目),接下来即可将编译好的库,导入到项目工程中使用。本文主要讲解如何将Protobuf库导入到虚幻中,并使用。

本文选用的Protobuf版本是protobuf-3.21.12

操作

  1. 创建C++空白项目
  2. 在项目Soruce文件夹下,添加ThirdParty文件夹,用于导入第三方Protobuf库
  3. 添加用于导入库的模块文件夹,命名为UEProtobuf(名称随意)
  4. 在文件夹内添加include(用于存放头文件)和lib(用于存放库)文件夹
  5. 创建UEProtobuf.Build.cs文件,用于构建模块配置
  6. 拷贝Protobuf项目中的源码头文件到模块include文件夹中
    src文件夹中,只需要拷贝后缀是.h和.inc文件即可,其他可删除
  7. 拷贝库文件到模块的lib文件夹中
  8. 配置Build.cs文件将如下内容拷贝到文件中
c#
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
using UnrealBuildTool;
using System.IO;

public class UEProtobuf : ModuleRules
{
	public UEProtobuf(ReadOnlyTargetRules Target) : base(Target)
	{
		Type = ModuleType.External;
		
		PublicSystemLibraryPaths.Add(Path.Combine(ModuleDirectory, "lib"));
		
		PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "include"));
		
		PublicSystemLibraries.Add("libprotobuf.lib");
		PublicSystemLibraries.Add("libprotoc.lib");
	}
}
  1. 右键uproject文件,在菜单中选择刷新solution

使用Protobuf库

  1. 导入Protobuf库的模块

在项目的build文件中,加入模块UEProject

c#
1
2
//ProtobufToturial.Build.cs文件中截取代码
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UEProtobuf" });
  1. 使用已经编译好的protobuf编译器(protoc.exe),将写好的protobuf文件编译成C++平台代码(这里需要你了解protobuf语法特点,并了解如何完成protobuf转换操作)。 protobuf文件内容如下:
protobuf
1
2
3
4
5
syntax = "proto3";
message Phone {
    int32 Number = 1;
    string Name = 2;
}
  1. 将生成的头文件和源文件拷贝到虚幻工程项目的source文件夹中(路径关系根据需求可调整)
  2. 在Rider中(VS操作基本一样),将头文件与源文件引入项目,操作如下:
  3. 测试代码

在Gamemode中添加指令函数,并在源文件中定义指令函数,编写如下测试代码。

头文件内容

c++
1
2
3
protected:
	UFUNCTION(Exec)
	void TestProtobuf();

源文件内容

c++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
void AProtobufToturialGameModeBase::TestProtobuf()
{
	//声明Protobuf类型数据
	Phone m_phone;
	m_phone.set_number(100);
	m_phone.set_name("这是一部iphone");

	//输出数据
	UE_LOG(LogTemp, Log, TEXT("%d"), m_phone.number());
	//输出文本
	UE_LOG(LogTemp, Log, TEXT("%s"), UTF8_TO_TCHAR(m_phone.name().c_str()));
}

编译工程时,会出现如下错误

1
2
3
  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文件中(双击错误跳转),将代码进行修改,参照如下:

c++
1
2
3
4
5
6
7
#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);
  }

改后

c++
1
2
3
4
5
6
7
8
//调整此段
#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);
  }

再次编译即可通过

  1. 运行查看结果

启用工程,将地图模式设置为项目Gamemode,通过唤出指令进行测试,即可得到测试结果。

1
2
3
Cmd: TestProtobuf
LogTemp: 100
LogTemp: 这是一部iphone

引擎版本:5.1.1

Protobuf版本:3.21.12

此模块UE4和UE5均可使用,如果你需要应用到自己工程,只需要将ThirdParty拷走,重新编译即可。

网盘资源 提取码: 4dcm