Pull to refresh

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

Reading time 3 min
Views 3K
Original author: Laurent Bédubourg

Предисловие


Это перевод заключительной, третьей части цикла статей о создании нативных библиотек расширения для OpenFL. Во второй части рассказавалось как создать библиотеку расширений для iOS. В данной части, будет рассказано о создании библиотеки расширений для платформы Android, на языке Java и, как будет видно далее, для Android сделать это несколько проще, чем для iOS.

Java, Haxe и все, все, все!


Для своей следующей игры, я придумал показывать справку в виде встроенной HTML страницы и нашел следующий проект: NMEWebview. Этот проект хорошо демонстрирует, как мы можем использовать код на Java в нашем приложении на haxe.

Пришло время проверить взаимодействие с кодом на Java.

Создадим каталог для расширения:
cd project
mkdir android
mkdir android/testextension

И файл TestExtension.java
package testextension;

class TestExtension {
    public static String doSomething(String in){
        return in+"\n"+in;
    }
}

testextension.TestExtension.doSomething(String):String наша тестовая функция и нам нужно экспортировать ее в haxe.

Так как мы пишем на Java, мы уже не можем использовать cpp.Lib.load для доступа к расширению и должны использовать для этого openfl.utils.JNI.

Вот таким образом я сделал обертку на haxe в TestExtension.hx:
#if android
// К сожалению, мы не можем использовать функции JNI до выполнения функции main.
// Я пробовал, верьте мне :)
private static var testextension_dosomething : Dynamic;

private static function init(){
    if (testextension_dosomething != null)
        return;
    testextension_dosomething = openfl.utils.JNI.createStaticMethod(
        "testextension/TestExtension",
        "doSomething",
        "(Ljava/lang/String;)Ljava/lang/String;"
    );
}
public static function doSomething(str:String) : String {
    init();
    return testextension_dosomething(str);
}
#end

openfl.utils.JNI.createStaticMethod работает аналогично cpp.Lib.load. Первые два параметра этой функции это названия класса и название статического метода, который мы собираемся использовать. А вот третий аргумент самая сложная часть — это сигнатура метода.

Можно сказать, что () обозначают метод, и то что внутри скобок это аргументы, а то что снаружи — тип результата.

(Ljava/lang/String;)Ljava/lang/String; соответствует String->String в haxe.

Подробнее про обозначение сигнатур в JNI (с примерами) вы можете прочесть здесь, но хочу заметить, что это первая ссылка, которую я нашел в Google. Я думаю, что существует и более простая документация.

У нас нет необходимости компилировать наше Java расширение перед использованием, компиляция будет происходить при сборке приложения и нам нужно указать как это делать.

Для этого в файл include.xml в каталоге с расширением добавим следующую строчку:
<java path="project/android" if="android" />

После этого, вызов TestExtension.doSomething() в приложении TestApp будет прекрасно работать.

Код из этой статьи вы можете найти в репозитории на GitHub'e.

Имейте в виду, что я также добавил файл android/Tweet.cpp (но не реализовал функцию Tweet), чтобы избежать условной компиляции и добавления #if ios по всему коду.

Следующее, что я хочу сделать в связке Java/haxe — научиться передавать HaxeObject и вызывать функции там и тут (на данный момент openfl.utils.JNI немного ограничен, но я думаю мы сможем экспортировать все необходимые C++ методы из JNI в haxe).

От переводчика


На этом заканчивается цикл статей о создании нативных библиотек расширений от Laurent Bédubourg. Цикл описывается необходимый минимум, достаточный, чтобы начать работу над своим расширением. Когда я начал работу над своим набором расширений, данных статей не было и информацию приходилось искать в различных блогах.
Если вы захотите создать расширение для Android и вам понадобятся возможности последних SDK, то вот здесь можно найти статью о том, как собрать расширение для нужной версии SDK.
Tags:
Hubs:
+6
Comments 0
Comments Leave a comment

Articles