제3자 라이브러리

제3자 C‍+‍+ 라이브러리를 모드에 추가하는 것은 가능하지만, 추가 설정이 필요합니다. 제3자 라이브러리는 모드 플러그인에 모듈로 포함되어야 합니다.

모듈 정의

먼저 다음 예제를 따르는 디렉터리 구조를 생성해야 합니다: Mods/<모드참조>/Source/ThirdParty/<third_party>Library/ 그리고 해당 라이브러리 이름으로 <제3자>Library.Build.cs라는 파일을 디렉터리에 배치합니다.

파일에는 모듈 이름과, 포함 경로 및 라이브러리 경로에 대한 참조가 포함되어야 합니다.

추천 구조는 inc(또는 include)에 라이브러리 헤더 파일을 포함하고, lib/<플랫폼이름>`에 컴파일된 라이브러리 파일을 포함하는 것입니다, 여기서 <플랫폼이름>언리얼 대상 플랫폼 이름 중 하나입니다. 현재 새티스팩토리는 `Win64Linux에 대해 출시되었습니다.

using System.IO;
using UnrealBuildTool;

public class <third_party>Library : ModuleRules
{
    public <third_party>Library(ReadOnlyTargetRules Target) : base(Target)
    {
        Type = ModuleType.External;
        PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "inc"));

        var PlatformName = Target.Platform.ToString();

        var LibFolder = Path.Combine(ModuleDirectory, "lib", PlatformName);
        if (Target.Platform == UnrealTargetPlatform.Win64)
        {
            PublicAdditionalLibraries.AddRange(Directory.EnumerateFiles(LibFolder, "*.lib"));
        }
        else if (Target.Platform == UnrealTargetPlatform.Linux)
        {
            PublicAdditionalLibraries.AddRange(Directory.EnumerateFiles(LibFolder, "*.a"));
        }
    }
}

공유(동적) 라이브러리

공유 라이브러리는 추가 설정이 필요합니다, 런타임 링커는 플러그인, 모드 및 게임의 관련 Binaries/<플랫폼이름> 폴더에서만 공유 라이브러리를 찾기 때문입니다.

.dll 또는 .so 파일을 소스 폴더에서 Binaries로 복사하려면, 모듈의 RuntimeDependencies 목록을 활용할 수 있습니다. 이것은 모드의 빌드 출력에 포함되어야 하는 파일을 표시하며, 원본 위치와 다른 위치로 파일을 복사할 수 있습니다. 이는 공유 라이브러리에 필요합니다.

언리얼 엔진은 newdelete 함수를 맞춤 메모리 관리 시스템을 사용하여 오버라이드합니다. 이로 인해 STL 객체를 외부에서 컴파일된 공유 라이브러리로 전달하는 것이 불가능합니다, 왜냐하면 한 쪽에서 new 함수로 할당되고, 다른 쪽에서 일치하지 않는 delete 함수로 해제되기 때문입니다. 이렇게 하면 FMallocBinned2 Attempt to realloc an unrecognized block 0000023E58B80000 canary == 0x0 != 0xe3와 유사한 충돌이 발생합니다.

using System.IO;
using UnrealBuildTool;

public class <third_party>Library : ModuleRules
{
    public <third_party>Library(ReadOnlyTargetRules Target) : base(Target)
    {
        Type = ModuleType.External;
        PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "inc"));

        var PlatformName = Target.Platform.ToString();

        var LibFolder = Path.Combine(ModuleDirectory, "lib", PlatformName);
        if (Target.Platform == UnrealTargetPlatform.Win64)
        {
            PublicAdditionalLibraries.AddRange(Directory.EnumerateFiles(LibFolder, "*.lib"));
        }
        else if (Target.Platform == UnrealTargetPlatform.Linux)
        {
            PublicAdditionalLibraries.AddRange(Directory.EnumerateFiles(LibFolder, "*.a"));
        }

        RuntimeDependencies.Add("$(BinaryOutputDir)", Path.Combine(LibFolder, "*.dll")); // Windows
        RuntimeDependencies.Add("$(BinaryOutputDir)", Path.Combine(LibFolder, "*.so")); // Linux
    }
}

모듈 사용

제3자 모듈을 정의한 후, 모드의 기본 모듈의 <모드참조>.Build.cs 파일에서 이를 공개 의존성으로 참조해야 합니다.

PublicDependencyModuleNames.AddRange(new string[] {"<제3자>Library"});

가져오기 오류

언리얼 엔진은 경고가 오류로 처리되는 기준이 더 엄격하지만, 일부 라이브러리는 이러한 경고를 무시합니다. 이는 사용 사례에 중요하지 않기 때문입니다.

이 경우, 해당 라이브러리에서 가져온 모든 항목을 여러 레이어의 호환성 매크로 및 헤더로 감싸야 합니다.

#include "Windows/WindowsHWrapper.h"
#include "Windows/AllowWindowsPlatformTypes.h"
#include "Windows/AllowWindowsPlatformAtomics.h"

PRAGMA_PUSH_PLATFORM_DEFAULT_PACKING
THIRD_PARTY_INCLUDES_START

#pragma push_macro("check")
#undef check

<원하는_임포트_입력>

#pragma pop_macro("check")

THIRD_PARTY_INCLUDES_END
PRAGMA_POP_PLATFORM_DEFAULT_PACKING

#include "Windows/HideWindowsPlatformAtomics.h"
#include "Windows/HideWindowsPlatformTypes.h"

라이브러리를 컴파일할 때 오류가 발생하는 경우 가져오기를 감싸더라도, 해당 오류를 수정하고 라이브러리를 다시 컴파일해야 합니다.

동일한 제3자 라이브러리를 사용하는 여러 모드

동일한 외부 라이브러리를 사용하는 여러 모드를 개발할 계획이라면 라이브러리를 보유할 의존성 모드를 만드는 것을 고려해야 합니다. 각 모드가 모듈로 라이브러리를 포함하더라도 런타임에 문제는 없지만(검증되지 않음), 개발 중에는 두 모드가 동시에 프로젝트에 있을 경우 언리얼이 빌드할 때 문제를 제기할 것입니다. 그리고 두 모드에서 제3자 모듈 이름이 동일할 경우 문제가 발생합니다.

기존 플러그인

사용하려는 라이브러리가 이미 완전한 uplugin인 경우, 프로젝트 폴더로 가져와 알파킷을 통해 패키징해 보십시오. 그것이 작동하면, 라이브러리는 별도의 모드로 출시될 수 있으며, 요구 사항은 일반 모드 종속성 시스템을 통해 처리됩니다. 배포하기 전에 라이브러리 제작자로부터 재배포 허가를 받는 것을 잊지 마십시오.