将Swift库集成到UE4中

最近,出现了将仅用Swift编写的代码集成到UE4上的项目中的问题。同时,未考虑选项“让我们快速重写Objective C中的所有内容”。我在任何地方都找不到现成的解决方案,而我经常(经常)要深入研究广度。该任务已成功解决,为了帮助其他人,我决定编写一个教程。



通常,如果您需要集成任何特定于iOS / macOS平台的代码,则将库程序集用作框架,该框架必须是静态的。代码本身是用目标C编写的。此外,依赖项是用项目构建脚本编写的MyProject.Build.cs,例如,如下所示:



if (Target.Platform == UnrealTargetPlatform.IOS)
{
    string ExtraPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "../ThirdParty"));
    PublicAdditionalFrameworks.Add(
        new Framework(
            "MyFramework",
            ExtraPath + "/" + "MyFramework.framework.zip"
        )
    );
}


对于Swift,您可以尝试以相同的方式进行操作,但是会出现问题-依赖某些语言库。链接警告将如下所示:



ld: warning: Could not find auto-linked library 'swiftFoundation'
ld: warning: Could not find auto-linked library 'swiftDarwin'
ld: warning: Could not find auto-linked library 'swiftCoreFoundation'
ld: warning: Could not find auto-linked library 'swiftCore'
ld: warning: Could not find auto-linked library 'swiftCoreGraphics'
ld: warning: Could not find auto-linked library 'swiftObjectiveC'
ld: warning: Could not find auto-linked library 'swiftDispatch'
ld: warning: Could not find auto-linked library 'swiftSwiftOnoneSupport'


之后,将出现标准错误,即在目标文件中未找到某些符号。您可以尝试查找上述每个库的位置,并通过L键指定指向它的路径,但是我决定切换到Framework动态类型,该类型将自行加载这些库。



, iOS :



dyld: Library not loaded: @rpath/MyFramework.framework/MyFramework
  Referenced from: /private/var/mobile/Containers/Bundle/Application/.../MyApp.app/MyApp
  Reason: image not found


, UE4 Framework, . IOS Toolchain , IOSPlugin.



plist , , :



<iosPListUpdates>
    <addElements tag="dict" once="true">
        <key>NSCameraUsageDescription</key>
        <string>The camera is used for live preview.</string>
    </addElements>
</iosPListUpdates>


copyDir. , , :



<init>
    <log text="Copy MyFramwork..."/>
    <copyDir src="/.../MyFramework.framework" dst="$S(BuildDir)/Frameworks/MyFramework.framework" />
</init>


, init. .



MyProject.Build.cs :



using UnrealBuildTool;
using System.IO;

public class MyProject : ModuleRules
{
    public MyProject(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

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

        if (Target.Platform == UnrealTargetPlatform.IOS)
        {
            string ExtraPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "../ThirdParty"));
            PublicAdditionalFrameworks.Add(
                new Framework(
                    "MyFramework",
                    ExtraPath + "/" + "MyFramework.framework.zip"
                )
            );

            string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath);
            AdditionalPropertiesForReceipt.Add("IOSPlugin", Path.Combine(PluginPath, "MyProject_IOS_UPL.xml"));
        }
    }
}


文件是MyProject_IOS_UPL.xml这样的:



<?xml version="1.0" encoding="utf-8"?>
<root>
    <init>
        <log text="Copy MyFramework..."/>
        <copyDir src="/.../MyFramework.framework" dst="$S(BuildDir)/Frameworks/MyFramework.framework" />
    </init>
</root>


在UE4中提供正常的动态框架支持之前,此解决方案是一种解决方法,但我对此完全满意。




All Articles