Предисловие
Это продолжение перевода серии статей о создании расширений для OpenFL от Laurent Bédubourg. В первой части мы создали простое расширение и скомпилировали его для нативных платформ (Linux/Windows, Android, iOS). Во этой части мы добавим в наше приложение на iOS возможность отправлять твиты.
Что мы узнаем:
- как структурировать исходный код нашего расширения для различных платформ
- как связать код на haxe и функции из нашего расширения
- как линковаться с iOS фреймворками (с фреймворком Twitter, в частности)
Что делать?
Давайте начнем с того, что посмотрим как структурирован, например, проект NME.
На первый взгляд Build.xml выглядит сложно и мы вернемся в нему позже. Посмотрев на содержимое каталога, мы увидим следующее:
- include/ содержит заголовочные файлы, которые будут реализованы в common/ и plaforms
- common/ платформо-независимый c++ код (более менее платформо-независимый, мы можем использовать #if defined(HX_xxxx) чтобы добиться максимальной платформо-независимости)
- common/ExternalIterface.cpp экспортирует функции в среду исполнения (DEFINE_PRIM)
- platform в данном каталоге содержатся реализации под конкретные платформы (iPhone, maс, windows и другие)
На мой взгляд такая структура выглядит довольно удобной, давайте и мы будем ее использовать.
Начнем с нашего предыдущего расширения, мы должны объявить функцию Tweet() в существующем файле include/Util.h (по уму, мы должны использовать отдельный заголовочный файл, но я сегодня слишком ленив для этого).
namespace testextension {
int SampleMethod(int inputValue);
bool Tweet(const char* msg);
}
Теперь нам необходимо реализовать ее для платформы iphone:
cd project
mkdir iPhone
Создадим файл iPhone/Tweet.mm:
#import <Foundation/Foundation.h>
#import <Twitter/Twitter.h>
namespace testextension {
bool Tweet(const char* message){
// Простите за этот кусок кода на Objective-C
// Я просто скопировал его из другого поекта
// Мы должны проверить инициализирован ли клиент твитера
// Но я оставлю эту задачу читателю для самостоятельного решения :)
NSString* str = [[NSString alloc] initWithUTF8String:message];
TWTweetComposeViewController* tweetView = [[TWTweetComposeViewController alloc] init];
[tweetView setInitialText:str];
TWTweetComposeViewControllerCompletionHandler completionHandler =
^(TWTweetComposeViewControllerResult result) {
[[[[UIApplication sharedApplication] keyWindow] rootViewController] dismissModalViewControllerAnimated:YES];
};
[tweetView setCompletionHandler:completionHandler];
[[[[UIApplication sharedApplication] keyWindow] rootViewController] presentModalViewController:tweetView animated:YES];
return true;
}
}
И зарегистрируем функцию Tweet в haxe, для этого отредактируем файл common/ExternalInterface.cpp:
static value testextension_tweet(value message){
// мы знаем, что message это строка и просто получим ее значение
const char* cStr = val_get_string(message);
// вызовем нашу функцию Tweet и вернем в haxe true или false
if (testextension::Tweet(cStr))
return val_true;
return val_false;
}
// зарегистрируем нашу функцию, наша функция принимает один аргумент
DEFINE_PRIM(testextension_tweet, 1)
DEFINE_PRIME, val_get_string, val_true и всё остальное являются частью hxcpp и определены в hx/CFFI.h.
Изучение ExternalInterface.cpp из NME поможет вам понять, как зарегистрировать ваши функции.
Часть haxe находится в TextExtension.hx и выглядит вот так:
class TestExtension {
// загружаем нашу функцию
private static var testextension_tweet = Lib.load("testextension", "testextension_tweet", 1);
// внутри типизированного метода вызываем нативную функцию
public static function tweet(message:String) : Bool {
return testextension_tweet(message);
}
}
Как скомпилировать
Мне пришлось приложить усилия, чтобы разобраться как скомпилировать и слинковать проект, но в результате все оказалось довольно просто.
Сперва необходимо создать файл project/Build.xml:
<!-- мы добавили этот список файлов для ios -->
<files id="iphone">
<file name="iPhone/Tweet.mm"/>
</files>
<!--
Я также был вынужден скомпилировать расширение для Мака, чтобы избавиться от
следующей ошибки:
"Library TestExtension version dev does not have a neko dll for your system"
-->
<files id="mac">
<file name="Mac/Tweet.mm"/>
</files>
В секцию с id = NDLL необходимо добавить файлы, которые будут компилироваться:
<files id="mac" if="mac"/>
<files id="iphone" if="ios"/>
И, наконец, мы должны добавить фреймворк Twitter в зависимости в include.xml. Через этот файл hxcpp узнает какие фреймворки необходимо добавить в наше приложение.
<dependency name="Twitter.framework" if="ios"/>
Я скомпилировал расширение, также как я делал это в первой части.
haxelib run hxcpp Build.xml -Dmac
haxelib run hxcpp Build.xml -Diphoneos -DHXCPP_ARMV7
haxelib run hxcpp Build.xml -Diphonesim
Как запустить
Чтобы протестировать работу расширения, я добавил в свое тестовое приложение следующий вызов:
TestExtension.tweet("This is my tweet message");
И запустил его в симуляторе и на моем iOS устройстве:
cd TestApp
openfl test project.xml iphone -simulator
openfl test project.xml iphone
Мы можем твитить используя нативный API из нашего приложения! Круто, не правда ли?! :)
Хочу отметить одну очень важную вещь — способ, которым я получал информацию — находил ее в исходном коде hxcpp и nme, на гитхабе.
Пытаясь заставить все это работать я столкнулся с несколькими проблемами. Если вы экспериментируете и у вас что-то не получается, не забывайте очищать каталоги ndl/ и project/obj и пересобирать весь проект. Я продолжал экспериментировать, пока не нашел подходящий формат для Build.xml и include.xml.
Единственной реальной сложностью является недостаток документации по формату Build.xml в hxcpp. Но, слава богу, есть примеры, на которых можно учиться.
Следующее, что я хочу сделать, попробовать собрать расширение под андроид, чтобы убедиться, что и на этой платформе все работает. Говорят, что не только разработать расширение на java, но и описать это процесс будет полезным :)
Я обновил репозиторий расширения на гитхабе, в надежде, что мой небольшой вклад будет полезен другим хаксерам! Надеюсь данное руководство будет работать на вашей системе… хотя иногда все идет не так как задумывается ;)
Автор: zzzzzzerg