Using UE4 w/ Google Protocol Buffers

So, I needed a UE4 plugin which uses Google Protocol Buffers (GPB). Easy enough. Unfortunately, it was harder than i thought to integrate it.

Setup: UE4 4.17, x64, Google Protocol Buffers (master branch, commit c7457e)

Here are the steps i did:
1. I used cmake-gui to generate the solution files for GPB

  • uncheck protobuf_MSVC_STATIC_RUNTIME
  • uncheck protobuf_BUILD_SHARED_LIBS
  • change /MDd to /MD

2. In the file generated_messages_table_driven.h

static_assert(std::is_pod<AuxillaryParseTableField>::value, "");

to

//static_assert(std::is_pod<AuxillaryParseTableField>::value, "");

3. In the build.cs of the module, I added the following function:

public bool LoadGoogleProtocolBuffers(ReadOnlyTargetRules Target)
{
bool isLibrarySupported = false;
if ((Target.Platform == UnrealTargetPlatform.Win64))
{
isLibrarySupported = true;
string LibrariesPath = Path.Combine(ThirdPartyPath, "libprotobuf", "lib");
Console.WriteLine("... LibrariesPath -> " + LibrariesPath);
PublicAdditionalLibraries.Add(Path.Combine(LibrariesPath, "libprotobufd" + ".lib"));
}
if (isLibrarySupported)
{
string IncludePath= Path.Combine(ThirdPartyPath, "libprotobuf", "include");
Console.WriteLine("... IncludePath -> " + IncludePath);
PrivateIncludePaths.Add(IncludePath);
}
Definitions.Add(string.Format("WITH_GPB_BINDING={0}", isLibrarySupported ? 1 : 0));
return isLibrarySupported;
}

4. I call this function from within the constructor of the module

5. I wrapped all includes of my *pb.h files with

#include "AllowWindowsPlatformTypes.h"
#include "...*.pb.h "
#include "HideWindowsPlatformTypes.h"'

6. Added the *pb.c files to the plugin project (private section)

7. I also had to ignore some warning:

#pragma warning (disable : 4800) // forcing value to bool true or false
#pragma warning (disable : 4125) // decimal digit terminates octal escape sequence
#pragma warning (disable : 4647) // behavior change __is_pod has different value in previous version
#pragma warning (disable : 4668) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'

Note: One thing I came across is the following issue with the check macro defined by UE4 and protobuf.

Here’s what I had to do in type_traits.h of protobuf:

template<typename B, typename D>
struct is_base_of {
typedef char (&yes)[1];
typedef char (&no)[2];
// BEGIN GOOGLE LOCAL MODIFICATION -- check is a #define on Mac.
//#undef check
// END GOOGLE LOCAL MODIFICATION
static yes checkUnrealFix(const B*);
static no checkUnrealFix(const void*);
enum {
value = sizeof(checkUnrealFix(static_cast<const D*>(NULL))) == sizeof(yes),
};
};

This might also work with the release version 3.4, I did not check that yet.

With this setup, I’m able to receive a protocol buffer send via TCP/IP and access all properties. I wasn’t able to test more.

If you have any questions, feel free to ask :)