Creating a Native Extension Library for OpenFL, Part Two

Original author: Laurent Bédubourg
  • Transfer
  • Tutorial

Foreword


This is a continuation of the translation of a series of articles on creating extensions for OpenFL by Laurent Bédubourg. In the first part, we created a simple extension and compiled it for native platforms (Linux / Windows, Android, iOS). In this part, we will add the ability to send tweets to our iOS application.

What we learn:
  • how to structure the source code of our extension for different platforms
  • how to link haxe code and functions from our extension
  • how to link with iOS frameworks (with the Twitter framework in particular)


What to do?


Let's start by looking at how the NME project is structured, for example .

At first glance, Build.xml looks complicated and we will return to it later. Looking at the contents of the directory, we will see the following:
  • include / contains header files to be implemented in common / and plaforms
  • common / platform-independent c ++ code (more less platform-independent, we can use #if defined (HX_xxxx) to achieve maximum platform independence)
  • common / ExternalIterface.cpp exports functions to the runtime (DEFINE_PRIM)
  • platform in this directory contains implementations for specific platforms (iPhone, mac, windows and others)

In my opinion, such a structure looks rather convenient, let us and we will use it.

Let's start with our previous extension, we have to declare the Tweet () function in the existing include / Util.h file (intellectually, we should use a separate header file, but today I am too lazy for this).
namespace testextension {
  int SampleMethod(int inputValue);
  bool Tweet(const char* msg);
}

Now we need to implement it for the iphone platform:
cd project
mkdir iPhone

Create an iPhone / Tweet.mm file:
#import 
#import 
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;
    }
}

And register the Tweet function in haxe, for this we edit the file 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 and the rest are part hxcpp and determined hx / CFFI.h .

Studying ExternalInterface.cpp from NME will help you understand how to register your functions.

The haxe part is in TextExtension.hx and looks like this:
class TestExtension {
// загружаем нашу функцию
private static var testextension_tweet = Lib.load("testextension", "testextension_tweet", 1);
// внутри типизированного метода вызываем нативную функцию
public static function tweet(message:String) : Bool {
    return testextension_tweet(message);
}
}

How to compile


I had to make an effort to figure out how to compile and link the project, but as a result, everything turned out to be quite simple.

First, create the project / Build.xml file:

In the section with id = NDLL, you need to add the files that will be compiled:

And finally, we need to add the Twitter framework depending on include.xml. Through this file, hxcpp will find out which frameworks to add to our application.

I compiled the extension, just as I did in the first part .
haxelib run hxcpp Build.xml -Dmac
haxelib run hxcpp Build.xml -Diphoneos -DHXCPP_ARMV7
haxelib run hxcpp Build.xml -Diphonesim

How to start


To test the operation of the extension, I added the following call to my test application:
TestExtension.tweet("This is my tweet message");

And launched it in the simulator and on my iOS device:
cd TestApp
openfl test project.xml iphone -simulator
openfl test project.xml iphone

IPhone application window
We can tweet using the native API from our application! Cool, isn't it ?! :)

I want to note one very important thing - the way I got the information - I found it in the source code hxcpp and nme, on the github.

Trying to make it all work, I ran into several problems. If you are experimenting and you are failing, do not forget to empty the ndl / and project / obj directories and rebuild the entire project. I continued to experiment until I found a suitable format for Build.xml and include.xml.

The only real difficulty is the lack of documentation on the Build.xml format in hxcpp. But, thank God, there are examples to learn from.

The next thing I want to do is try to build an extension for android to make sure that everything works on this platform too. They say that not only developing the extension in java, but also describing this process will be useful :)

I updated the extension repository on the github , in the hope that my small contribution will be useful to other hackers! I hope this guide will work on your system ... although sometimes everything goes wrong as intended;)

Also popular now: