Русский
Русский
English
Статистика
Реклама

Из песочницы Интеграция библиотеки на Swift в UE4

Недавно возникла задача интеграции кода, который был написан только на Swift в проект на UE4. При этом вариант "давайте быстренько перепишем все на Objective C" не рассматривался. Готового решения нигде не нашел, пришлось, как это часто бывает, копать и вширь и вглубь. Задача была успешно решена и чтобы помочь кому-то еще, решил написать туториал.


Обычно, если нужно интегрировать какой-либо специфичный для iOS/macOS платформы код, используется сборка библиотеки в виде Framework, который должен быть статический. Сам же код пишется на Objective 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="http://personeltest.ru/aways/habr.com/.../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="http://personeltest.ru/aways/habr.com/.../MyFramework.framework" dst="$S(BuildDir)/Frameworks/MyFramework.framework" />    </init></root>

Это решение в некотором роде обходной путь, пока не появится нормальной поддержки динамического Framework в UE4, но меня оно полностью устроило.

Источник: habr.com
К списку статей
Опубликовано: 09.10.2020 14:15:38
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Программирование

Swift

Unreal engine

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru