Создание нативной библиотеки расширений для OpenFL, часть вторая

от автора

Предисловие

Это продолжение перевода серии статей о создании расширений для 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 

Окно приложения на iPhone
Мы можем твитить используя нативный API из нашего приложения! Круто, не правда ли?! 🙂

Хочу отметить одну очень важную вещь — способ, которым я получал информацию — находил ее в исходном коде hxcpp и nme, на гитхабе.

Пытаясь заставить все это работать я столкнулся с несколькими проблемами. Если вы экспериментируете и у вас что-то не получается, не забывайте очищать каталоги ndl/ и project/obj и пересобирать весь проект. Я продолжал экспериментировать, пока не нашел подходящий формат для Build.xml и include.xml.

Единственной реальной сложностью является недостаток документации по формату Build.xml в hxcpp. Но, слава богу, есть примеры, на которых можно учиться.

Следующее, что я хочу сделать, попробовать собрать расширение под андроид, чтобы убедиться, что и на этой платформе все работает. Говорят, что не только разработать расширение на java, но и описать это процесс будет полезным 🙂

Я обновил репозиторий расширения на гитхабе, в надежде, что мой небольшой вклад будет полезен другим хаксерам! Надеюсь данное руководство будет работать на вашей системе… хотя иногда все идет не так как задумывается 😉

ссылка на оригинал статьи http://habrahabr.ru/post/186722/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *