在UnrealEngine4中使用Google Protobuf


轉自:https://blog.csdn.net/or_7r_ccl/article/details/54986393

在UnrealEngine4中使用Google Protobuf

       UE有一套自己的編譯規則,如何在游戲中添加第三方庫官方有一篇很詳細的文檔(Linking Static Libraries Using The Build System)。
       簡單來說,第三方庫一般放在’Source/ThirdParty’目錄下,建一個目錄,把需要包含的頭文件以及編譯好的庫都放在這里,然后寫一個對應的[LIBNAME].Build.cs文件,在這個文件里需要告訴編譯器需要修改的設置,例如添加那些包含目錄以及鏈接庫。在游戲工程使用時,需要在本工程文件的[APPNAME].Build.cs中添加對該庫的引用,就像下面這樣

PublicDependencyModuleNames.AddRange(new string[] { 
   "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "libprotobuf" });

       對第三方庫的使用,可以參照UnrealEngine的源碼,在它的源碼目錄’Source/ThirdParty’里,有一大堆第三方庫,不過這些庫都是預先編譯好的.lib和.a,如何編譯出這些庫官方並沒有提供詳細的文檔說明。對於Windows環境來說比較簡單,首先是使用和UE編輯器同樣的VisualStudio版本,例如目前最新的4.14使用的是VS2015,並且在編譯中使用/MD選項。google protobuf本身提供了一套cmake編譯腳本,可以很方便的編譯出所需要的lib文件。
       比較麻煩的是Linux平台,UE提供了專門的clang工具鏈來作為Linux和Android平台的編譯工具,可以參照官方的這篇文檔下載安裝(Compiling For Linux),不過這套工具鏈中並沒有對應的make工具,所以我從UE源碼中的UnrealBuildTool工具中把編譯參數還原出來,手動寫了一套python腳本來完成probobuf的編譯。
       為了適應UE4的環境,需要做一些改動,首先是protobuf中使用了類似於UINT這樣的數據類型,而這種數據類型在UE4的源碼中已經被屏蔽,具體可以參考UE源碼中DisableOldUETypes.h文件的說明,為了使兩者兼容,需要在protoc產生的.pb.h文件中添加#include “AllowWindowsPlatformTypes.h”和#include “HideWindowsPlatformTypes.h”兩行代碼。

#ifdef _MSC_VER
#include "AllowWindowsPlatformTypes.h" 
#endif
 
//include other header file
 
#ifdef _MSC_VER
#include "HideWindowsPlatformTypes.h" 
#endif

 另外protobuf源碼中有一個文件使用了byteswap.h這個頭文件,不幸的是,UE4源碼中有一個ByteSwap.h文件,在clang編譯器中產生編譯錯誤,需要做一定的修改。

//google/protobuf/stubs/port.h, line 91
//#include <byteswap.h>  // IWYU pragma: export
#include <bits/byteswap.h>
#define bswap_16(x) __bswap_16 (x)
#define bswap_32(x) __bswap_32 (x)
#define bswap_64(x) __bswap_64 (x)

我把最終編譯好的庫以及所使用的的編譯腳本放到了github上,所需環境如下

軟件    版本    備注
Google Protobuf    3.1.0     
Visual Studio    2015     
clang    3.9.0    EPIC提供改造過的工具鏈,需要參照這篇官方文檔下載安裝
CMake    2.8以上    需要把cmake.exe所在路徑加入到PATH路徑中
Unreal Engine Source    4.14.3    參照官方文檔下載並編譯源碼
Python    3.x or 2.x     
This entry was posted in 未分類 and tagged 程序. Bookmark the permalink.

Project Settings -》 packaging -》 Packaging選項中,有多個設置項來設置打包時要排除或者包含的文件夾,比如:設置哪些目錄不參與cook,以及哪些目錄在打包時需要拷貝進來的目錄(比如與UE4的文件IO API無關的配置文件等等)

注意:這些設置的目錄必須在Content目錄下

 

對於這些自定義文件(非UE4支持的文件格式,比如text文本),安裝后的相對路徑也不同:

Adding custom files to the Android content.
https://answers.unrealengine.com/questions/120796/adding-custom-files-to-the-android-content.html

On UE 4.7.3 I found a better solution.

On Android I'm using a PathToAndroidPaths function fromEngine\Source\Runtime\Core\Private\Android\AndroidFile.cpp

On IOS I'm using a ConvertToIOSPath function from Engine\Source\Runtime\Core\Private\IOS\IOSPlatformFile.h

On PC I'm using a FPaths::ConvertRelativePathToFull function fromEngine\Source\Runtime\Core\Public\Misc\Paths.h

Most of those function are private, so I made a new, public function that use them for converting relative path to the absolute one.

The ConvertRelativePathToFull from FPaths works correctly only for PC, it doesn't return correct absolute paths for mobile devices.

 

其他參考:

Additional Asset Directories not Copied to Packaged Build
https://answers.unrealengine.com/questions/241947/additional-asset-directories-not-copied-to-package.html

 

ios開發使用xcode6打包protobuf靜態庫 解決了 官方引用 protobuf 導致的沖突問題 包含 arm64 支持

轉自:https://blog.csdn.net/xiaofei125145/article/details/39697145

1、下載 protobuf-2.5.0-mast ,並解壓

2、在解壓后的  目錄內部建立一個 目錄 名字隨便寫,我這里寫的 是 xcodeProject 如圖:

 

3、新建一個 靜態庫工程  在剛才 的  xcodeProject 文件夾內.

4,將工程中 自帶的 哪個 類 刪除 ,也就是刪除 下圖 中 的  protobufXcode6 那個類 。

5, 將  protobuf-2.5.0-master/src/google  文件夾 添加到  剛才新建的 靜態庫工程 中 ,注意 不需要 勾選 copy 復選框,注意勾選add to target ,如圖 。

6、 將  google/protobuf/compiler/文件夾 從工程中 移除 。

7、 將 google 中所有的 test 文件 刪除 ,可在 文件中 搜 test 如圖 ,然后 刪除  google 文件夾中 包含 test 的文件 如圖。

8、添加 頭文件 引用 路徑,如圖。

9、生成 config.h 頭文件 。 打開終端 , cd 到 protobuf 跟目錄下 , 運行  ./configure 腳本   就可以生成 config.h 文件 ,生成后 將 config.h 文件 添加到 xcode  工程 中 ,如圖

10、 修改 平台 支持 宏定義 ,  將下面三行 添加到  stubs/platform_macros.h  中 ,如下圖。

#elif defined(__aarch64__)

#define GOOGLE_PROTOBUF_ARCH_ARM 1

#define GOOGLE_PROTOBUF_ARCH_64_BIT 1

11、 命名空間修改 ,由於  APPLE 官方 已經 在 手機的 框架內 使用了 google 的 protobuf  ,如果你 依然使用 protobuf 中的 命名空間 google 的話 ,在 64 的 系統中 會 導致 崩潰 ,所以 需要修改 命名空間 ,如下圖 添加 一行 宏定義 ,

添加位置 , google/protobuf/stubs/common.h  如圖 

#define google googleZhiGuang

 

12、添加需要 copy 的 頭文件  ,如下圖 ,點擊 加號 以后  選中 所有的  .h 文件  然后 點擊 Add 

13 、修改  Scheme ,切換到 Run 選項 ,點擊 右側的  info ,build configuration 設置為  Release , 如圖 。

 

14、最后接  build 就可以生成了  ,注意 編譯的時候 選擇 模擬器的話 編譯 出來的  是  模擬器 對應 的  i386 的 架構的 ,編譯 armv7,armv7s,arm64 的 需要 選擇 手機 ,沒有手機的話就 選 ios Device  。

15、 找到  lib 和 頭文 件 , 

build 完 之后 ,如圖 ,在  product 文件 上 點擊 右鍵 showinfinder 就可以了 ,include 文件夾中是 對應的 頭文件 。

 

UE4+Protobuf

需要把protobuf 源碼直接復制到UE4c++項目里面

修改 libprotobuf 源碼

主要是去掉兩個宏開關 GOOGLE_PROTOBUF_NO_RTTI 和 HAVE_PTHREAD

去掉 HAVE_PTHREAD 宏

在非 Windows 平台下都要打開 HAVE_PTHREAD 宏

打開 google/protobuf/stubs/common.cc,把兩個地方的 elif defined(HAVE_PTHREAD) 改成 #else

並且把第一處以下兩行代碼刪除

#else
#error "No suitable threading library available."

去掉 GOOGLE_PROTOBUF_NO_RTTI 宏

在所有平台下都要禁用 RTTI,因為 UE4 禁用了 C++ 的運行時類型識別(typeid 和 dynamic_cast)

打開 google/protobuf/arena.h,將

#ifndef GOOGLE_PROTOBUF_NO_RTTI
#define RTTI_TYPE(type) (&typeid(type)) #else #define RTTI_TYPE_ID(type) (NULL) #endif

改為
#define RTTI_TYPE_ID(type) (NULL)

打開 google/protobuf/generated_message_reflection.h,將
#if defined(GOOGLE_PROTOBUF_NO_RTTI) || (defined(_MSC_VER)&&!defined(_CPPRTTI))
	return NULL; #else return dynamic_cast<To>(from); #endif

改為
return NULL;

#if defined(GOOGLE_PROTOBUF_NO_RTTI) || (defined(_MSC_VER)&&!defined(_CPPRTTI))
	bool ok = &T::default_instance9) == from->GetReflection()->GetMessageFactory()->GetPrototype(from->GetDescriptor()); return ok ? down_cast<T*>(from) : NULL; #else return dynamic_cast<To>(from); #endif

改為
bool ok = &T::default_instance9) == from->GetReflection()->GetMessageFactory()->GetPrototype(from->GetDescriptor()); return ok ? down_cast<T*>(from) : NULL;

打開 google/protobuf/stubs/casts.h,刪除以下兩處代碼

#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
	assert(f == NULL || dynamic_cast<To>(f) != NULL); // RTTI: debug mode only! #endif

#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
	// RTTI: debug mode only! assert(dynamic_cast<ToAsPointer>(&f) != NULL); #endif

禁用編譯警告

因為 UE4 會將一些編譯警告當成錯誤,所以要將編譯過程中 libprotobuf 中的警告禁用掉

轉載:https://github.com/jashking/UE4Protobuf


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM