[Программирование] Интеграция библиотеки на Swift в UE4
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Недавно возникла задача интеграции кода, который был написан только на 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="/.../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>
Это решение в некотором роде обходной путь, пока не появится нормальной поддержки динамического Framework в UE4, но меня оно полностью устроило.
===========
Источник:
habr.com
===========
Похожие новости:
- [Программирование, Карьера в IT-индустрии] «Сферический Конь» в микросервисах, Тарантино, слежка и высокоградусный HR — треш-истории собеседований от разработчиков
- [Open source, Rust, Компиляторы, Программирование, Системное программирование] Rust 1.47.0: const generics для массивов, LLVM 11, Control Flow Guard и сокращение трассировок (перевод)
- [Программирование, TypeScript] Chorda 2.0. Как я потерял и нашел API
- [Программирование, Изучение языков] Hi Programming Language: linked list
- [Программирование, .NET, Управление продуктом, Управление персоналом, Читальный зал] Меня перевезли в другую страну и через две недели выставили на мороз — потому что передумали нанимать
- [Программирование, C++, Биографии гиков, Интервью] Тридцать лет С++. Интервью с Бьерном Страуструпом (перевод)
- [IT-компании, Будущее здесь, Игры и игровые приставки, Транспорт] Развлекательная система электромобиля GMC Hummer будет работать на игровом движке Unreal Engine
- [C++, Алгоритмы, Программирование] Под капотом сортировок в STL
- [Open source, Программирование, C++] What's new in rotor v0.09
- [Тестирование мобильных приложений, Разработка под iOS] Cucumber и BDD. Пишем UI-автотесты на iOS
Теги для поиска: #_programmirovanie (Программирование), #_swift, #_unreal_engine, #_programmirovanie (
Программирование
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 23:50
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Недавно возникла задача интеграции кода, который был написан только на 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="/.../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> Это решение в некотором роде обходной путь, пока не появится нормальной поддержки динамического Framework в UE4, но меня оно полностью устроило. =========== Источник: habr.com =========== Похожие новости:
Программирование ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 23:50
Часовой пояс: UTC + 5