UE As Lib机制初探

UE4.27 has introduced a new mechanism that allows UE to be compiled into a library, enabling it to be embedded in external programs, which can then drive the engine’s execution and message communication. However, the official documentation has not yet been released. I analyzed the relevant code in the engine and proposed a practical solution for UE as Lib, which can theoretically be implemented in engine versions before 4.27, although it may be inconsistent with the official documentation released later. The related research content will also be continuously updated in this article.

Firstly, I believe that UE as Lib is not provided as a static link library because the engine contains a large amount of code dependent on UHT and UBT, along with many template implementations. Compiling an independent Lib is very troublesome and requires the extraction of a lot of code during use. Therefore, I think UE as Lib is provided by compiling the engine into a DLL, driven by the external program through the exported symbols of the DLL.

Note: Currently, UE as Lib can only be used on Windows platforms.

A new Runtime Module has been added in UE 4.27: UELibrary, which exports symbols for external programs driving the engine.

The exported symbols are:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
extern "C"
{
/**
* Initializes UE as a library.
*
* @param hInst The instance of the outer application which wants to embed UE.
* @param hWnd The window of the outer application into which UE is to be embedded.
* @param CmdLine The command line to pass to UE - should contain a .uproject file and map to load at minimum.
*
* @return Zero if creation was successful, non-zero if an error occurred.
*
* @note UE can currently only be embedded in a single window.
* @note There is an A and W overload for different character widths of the command line argument. Typical usage
* should be to use the UELibrary_Init function which maps to the appropriate overload for the outer
* application's Unicode setting.
*/
UELIBRARYAPI int UELibrary_InitA(HINSTANCE hInst, HWND hWnd, const char* CmdLine);
UELIBRARYAPI int UELibrary_InitW(HINSTANCE hInst, HWND hWnd, const wchar_t* CmdLine);

#ifdef UNICODE
#define UELibrary_Init UELibrary_InitW
#else
#define UELibrary_Init UELibrary_InitA
#endif


/**
* Ticks the UE library. This should be called frequently by the outer application.
*
* @return Zero if ticking was successful, non-zero if an error occurred.
*/
UELIBRARYAPI int UELibrary_Tick();


/**
* Passes windows messages from the outer application to the UE library.
*
* @param hWnd As per WndProc.
* @param message As per WndProc.
* @param wParam As per WndProc.
* @param lParam As per WndProc.
*
* @return As per WndProc.
*/
UELIBRARYAPI LRESULT UELibrary_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);


/**
* Shuts down the UE library.
*
* @return Zero if shutdown was successful, non-zero if an error occurred.
*
* @note UE cannot be started up again once shut down.
*/
UELIBRARYAPI int UELibrary_Shutdown();
}

Four exported functions are provided for initializing the engine, ticking, passing messages, and shutting down the engine, confirming the previous inference that the engine is compiled into a DLL, driven by external programs through these four functions.

Regarding how to compile UE as Lib, I provide an idea. First, we need to clarify the requirements:

  1. Compile the engine into a standalone DLL
  2. Depend on the exported symbols of the UELibrary module
  3. Must compile the engine through UE’s build system

To achieve these requirements, we need to understand UE’s build system.

Note: UE’s UE as Lib can also compile game projects into DLLs, driven by external programs to start the game. Just transfer the following operations from Program to the game project’s Target.

UE modules must be dependent on the Target to be compiled through UE’s build system. I previously wrote an article on how to implement console or WinGUI programs with UE as a library: Create A Standalone Application in UE4. In this article, I provided an open-source tool ue4program, which makes it easy to create a StandaloneApplication program that depends on the UELibrary module. Compile this Program, and the UELibrary module along with the dependent modules will be compiled within it.

Then, Program is defaulted to compile as an exe. To realize UE as Lib compiled into a DLL, we essentially compile the Target of Program as DLL!

First, create a Standalone Application template using hxhb/ue4program:

1
2
# ue4program.exe ProgramName
$ ue4program.exe UEProgram

Place the created directory under the engine’s Source/Programs, execute GenerateProjectFiles.bat to refresh the solution, and you will see the newly created Program project in UE4.sln.

Add the UELibrary module as a dependency to UEProgram:

1
PrivateDependencyModuleNames.Add("UELibrary");

Then edit UEProgram‘s Target.cs, changing the LinkType:

1
LinkType = TargetLinkType.Monolithic;

This will compile all code into a final binary, while the default in UE is Modular, allowing access to other modules via DLL.

It is also necessary to change bShouldCompileAsDLL:

1
2
// Whether this target should be compiled as a DLL. Requires LinkType to be set to TargetLinkType.Monolithic.
bShouldCompileAsDLL = true;

By default, this is false, which would compile the Program into an exe, but our goal is to create a DLL. Add the UE_LIBRARY_ENABLED=1 macro, as only when this macro is set to 1 will the implementation code for the exported symbols be included in UELibrary:

1
GlobalDefinitions.Add("UE_LIBRARY_ENABLED=1");

After these modifications, compile the UEProgram project, and once the compilation is complete, you will find UProgram.dll in the engine’s Binaries/Win64.

It includes the engine code and the exported symbols from UELibrary, which can be loaded and executed in external programs using OpenLibrary, following the conventional C++ method of calling dynamic link libraries. After compiling the DLL, UE as Lib is realized, allowing users to call it in regular programs, independent of UE’s build system.

To summarize briefly, UE as lib is not entirely new; it simply exports the API for driving the engine. In engine versions prior to 4.27, it can still be achieved by implementing a UELibrary module to export symbols, following the method outlined in this article for dynamic linkage of the engine.

Due to time constraints, this is all the analysis provided for now. As for how to embed the compiled DLL into third-party programs to drive the engine, I will supplement that later when I have time.

Related links:

未完待续。

Scan the QR code on WeChat and follow me.

Title:UE As Lib机制初探
Author:LIPENGZHA
Publish Date:2021/08/24 09:34
World Count:3.9k Words
Link:https://en.imzlp.com/posts/26475/
License: CC BY-NC-SA 4.0
Reprinting of the full article is prohibited.
Your donation will encourage me to keep creating!