GET Developing Air Native Extensions (ANE) for OS X / Sudo Null IT News FREE
Hello to wholly habroyuzery. I would like to share the go through of creating native extensions for OS X.
Strain is merely an awesome cross-platform environment. Until it comes to using some kind of chips unique to the chopine. Information technology was this problem that I encountered when I was apt the task of turning a browser flash game into a desktop unrivalled for OS X. Complete this using the Publicise environment was done by me in a couple of hours and I wish non describe this process, since in Google this The topic is full of information. The most engrossing thing began when it became necessary to tie in several Apple services to the gritty, such as GameCenter, In-App-Buy up, etc. And here I ran into difficulties. The fact is that there are a caboodle of ready-made ANEs, including inexact ones. But the trouble is that totally these solutions make for only if for iOS. For Oculus sinister X, at that place's neither ready-made libraries,
Now I want to roll up all the assembled knowledge and experience in one place and share with you to at least slightly repress the pain that you have to go through, if you decide to make up native libraries for poppy too. Although later on the quaternity formulated extensions for OS X they do not seem so complicated and sophisticated.
So. For work I used:
Line 16;
Flex 4.6.0;
Adobe brick Dash Builder 4.6 or IntelliJ IDEA 14 (Flash Builder was victimised to write the library, although the same can cost done in IntelliJ IDEA. But the project itself I developed in IntelliJ IDEA. It's a matter of taste, I suppose);
Xcode 6.1.1;
OS X Yosemite (10.10.1);
I testament divide the entire process of creating Cardinal into 3 parts.
Part one. Objective-c
I think it's more logical to get down creating native extensions by writing the all but native code, although in any case, most likely you will have to return to changing the native code much than once.
We start by creating a new project in Xcode. File -> New -> Project ... (Cmd + Transmutation + N). Next, select OX X -> Fabric & Program library -> Cocoa Framwork.
We occur upward with a name for our framework. The nominate can represent anything, in the future, it will non be used in any manner in our upcoming native program library.
After that, we have an empty picture with one header file.
If the native library is planned to implement four-needled single functions that somehow need to be performed in Objective-C, then we can behave without a coping file using only the carrying out register (* .m). Merely I wish describe working with a fully fledged class.
Ahead writing code, you need to add together the Adobe Transmit.framework library to the project. Right-click on the project, and select Summate files to "...". I hope you already have got a fresh version of the AIR environment, because information technology stores the library that we ask. You can find it hither: ../AIR_FOLDER/runtimes/line/mac/Adobe brick AIR.framework.
After that, the protrude volition take care something like this:
You also need to set up a 32-chip poin platform (i386) for the project (not for the purpose). At the time of writing, Adobe AIR.framework worked only for 32-bit platforms. In the equal project settings in Build Settings, anticipate automatic reference, and set Objective-C Automatic Reference Counting to No.
I also change the paths of the output files thusly that they are in the same place As the source. To whom IT is more favourable.
Get-go of altogether, we need to specify the initializers of the context and the library itself (optionally, you can also delimit finalizers).
First, define a context initializer. It volition be called, curiously enough, when initializing the context of use in the as3 part, only more on that subsequently. When using several native libraries in a project, it is very important to holler initializers unique names. The context initializer also defines the functions that will exist available from as3 inscribe.
Sol. We declare a context initializer as follows:
FREContext AirCtx = nil; //Глобальная переменная контекста void MyAwesomeNativeExtensionContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet) { NSLog(@"[MyANE.Obj-C] Ingress ContextInitinalizer()"); *numFunctionsToTest = 1; //Количество функций, которые будут доступны из as3 кода. Очень важно чтобы число соответствовало реальному числу функций. Добавляем новую функцию - увеличиваем значение. FRENamedFunction* func = (FRENamedFunction*) malloc(sizeof(FRENamedFunction) * *numFunctionsToTest); func[0].name = (const uint8_t*) "initLibrary"; // Имя функции, по которому мы будем обращаться к ней из as3. func[0].functionData = Invalid; // Всегда Nix. Так и не нашёл случаев применения без Nothing. func[0].function = &init; // Ссылка на FREObject(функцию) в ojbective-c коде // Прочие функции // func[n].name = (const uint8_t*) "key out"; // func[n].functionData = data; // func[n].operate = &function; *functionsToSet = func; AirCtx = ctx; NSLog(@"[MyANE.Obj-C] Exiting ContextInitinalizer()"); }
It is worth noting that the NSLog function, which outputs a substance to the console, will also output a message in the form of trace in the IDE console in which you are developing the independent externalize.
Now we define the initializer of the library itself. In it, we indicate a link to the initializer and context finalizer. We will use it subsequently in the assembly of the library:
void MyAwesomeNativeExtensionInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet, FREContextFinalizer* ctxFinalizerToSet ) { NSLog(@"[MyANE.Obj-C] Entering ExtInitializer()"); *extDataToSet = NULL; *ctxInitializerToSet = &adenylic acid;MyAwesomeNativeExtensionContextInitializer; // Инициализатор контекста *ctxFinalizerToSet = &MyAwesomeNativeExtensionContextFinalizer; // Финализатор контекста(опционально) NSLog(@"[MyANE.Obj-C] Exiting ExtInitializer()"); }
Future, we describe our alone function available from the action script code. Inside this function, we can call various native Objective-C methods, including victimization the iOS SDK:
FREObject (init) (FREContext linguistic context, void* functionData, uint32_t argc, FREObject argv[]){ NSLog(@"[MyANE.Obj-C] Howdy World!"); return null; }
For convenience, you keister use the directive:
#define DEFINE_ANE_FUNCTION(fn) FREObject (fn)(FREContext context, void* functionData, uint32_t argc, FREObject argv[])
Using the directive described above, you can define a function so much easier and shorter:
DEFINE_ANE_FUNCTION(init){ NSLog(@"[MyANE.Obj-C] How-do-you-do World!"); return zip; }
Make the build (Bidding + B). As a result, in the way that we indicated at the selfsame beginning, the framework should have appeared, with a cite identical to the name that we indicated, again at the beginning.
The simplest Objective-C library is ready. The only thing it can do is print a string in trace. Simply to demonstrate the work will do. Now we pauperization to create the second half of our ANE - AS3 library.
Seed
Myane.h
#import #import //! Project version number for MyANE. FOUNDATION_EXPORT doubly MyANEVersionNumber; //! Plan version string for MyANE. FOUNDATION_EXPORT const unsigned woman MyANEVersionString[]; @user interface MyANE : NSObject @close
MyANE.m
#import "MyANE.h" #define DEFINE_ANE_FUNCTION(fn) FREObject (fn)(FREContext context, invalidate* functionData, uint32_t argc, FREObject argv[]) @implementation MyANE @end FREContext AirCtx = nil; DEFINE_ANE_FUNCTION(init){ NSLog(@"[MyANE.Obj-C] Hello World!"); return cypher; } empty MyAwesomeNativeExtensionContextInitializer(nihility* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet) { NSLog(@"[MyANE.Obj-C] Entering ContextInitinalizer()"); *numFunctionsToTest = 1; FRENamedFunction* func = (FRENamedFunction*) malloc(sizeof(FRENamedFunction) * *numFunctionsToTest); func[0].identify = (const uint8_t*) "initLibrary"; func[0].functionData = NULL; func[0].function = &ere;init; *functionsToSet = func; AirCtx = ctx; NSLog(@"[MyANE.Obj-C] Exiting ContextInitinalizer()"); } void MyAwesomeNativeExtensionContextFinalizer(FREContext ctx) { } emptiness MyAwesomeNativeExtensionInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet, FREContextFinalizer* ctxFinalizerToSet ) { NSLog(@"[MyANE.Obj-C] Entering ExtInitializer()"); *extDataToSet = NULL; *ctxInitializerToSet = &MyAwesomeNativeExtensionContextInitializer; *ctxFinalizerToSet = &MyAwesomeNativeExtensionContextFinalizer; NSLog(@"[MyANE.Obj-C] Exiting ExtInitializer()"); } void MyAwesomeNativeExtensionFinalizer(void* extData) { }
Part two. Action script
To create a library for Action Script, you canful use any IDE, with the possibility of developing in ActionScript. But I used the canonical IDE for so much purposes - Flash Builder.
Creating a program library is very simple: File -> Create -> Flex Library Project.
We name our library, and be sure to connect the Adobe brick AIR libraries. In fact, we do this for unrivalled single class, which will allow us to knead with context.
Immediately make up a new ActionScript class (you can, and information technology will be even more convenient to make over information technology in the default package), inheriting it from ostentation.events.EventDispatcher (in general, you can inherit from anything, but you give the axe not inherit at all, but the EventDispatcher class testament allow dispatch events to the instance, which is very useful when working with the iOS SDK, where some of the requested data (list of Gigahertz friends, list of on hand IAPs) does not come immediately). This will represent our main class, which we will enjoyment when workings with the library.
Forward we need to get an representativ of the context. This is done equally follows:
var extCtx:ExtensionContext = ExtensionContext.createExtensionContext("my.awesome.homegrown.extension", nada);
The static createExtensionContext method creates an extensionContext instance. Here we must pass the Idaho of our extension, in this case "my.awful.native.extension", as comfortably as the context type. Type essential be mere lonesome in suit of several library implementations. If one implementation is aforethought, then null can live passed as a case.
Concurrently in the projection can equal used only one (singleton) instance, the linguistic context of unrivaled, specialized type. Personally, after a bunch of created pure extensions, I never had the need for octuple implementations of this extension. So in this type, having one single implementation, we volition basically have one instance for the entire ANE. Therefore, the constructor necessarily to be named formerly, and in the future just get the already created object.
The easiest selection to carry out is to outcry a certain static subprogram that will return an instance of the object, or create a new ace through and through the constructor if there is none.
Prime, we describe the constructor (which we will never call from the project):
private unmoving var _instance:MyANE; // Статичный экземпляр класса one-on-one var extCtx:ExtensionContext; // Контекст public function MyANE(target:IEventDispatcher=cipher) { if (!_instance) { if (this.isSupported) { extCtx = ExtensionContext.createExtensionContext("my.awesome.native.telephone extension", null); // Создание контекста if (extCtx != null) { trace('[MyANE.AS3] extCtx is sanction'); } other { trace('[MyANE.AS3] extCtx is null.'); } } _instance = this; } other { throw Computer error('[MyANE.AS3] This is a singleton, employ getInstance, answer non call the constructor now'); // Вызываем ошибку, если пытаемся вызвать конструктор } }
You also motivation to verify that ANE is trying to run on a Mac.
public function pay off isSupported():Boolean { return Capabilities.manufacturer.indexOf('Mac') > -1; }
Nowadays we describe the function that we bequeath access each time we need to get an instance of our program library.
public unchanging affair getInstance():MyANE { return _instance != null ? _instance : new MyANE(); }
At this tip, we have completed the initialisation. Now you can use the methods from Objective-C. You can call a function from the inborn code by the method of the context instance class call (), which essential be passed as an argument one of the names of the functions specified in the circumstance initializer in the native code, atomic number 3 well As the parameters of the social function. In this example, we have delineated only one and only office called "initLibrary". She does non accept any parameters, well, we bequeath not reach anything.
in the public eye use init():null { extCtx.call("initLibrary"); }
Hold open the project. The library is mechanically compiled, and away nonpayment, information technology is placed in the bin directory, at the solution of the design.
Thus, we provided the about basic functionality. Today you can go to the dying part.
Source
software packag { import flash.events.EventDispatcher; importee flash.events.IEventDispatcher; import flash.external.ExtensionContext; implication gimcrack.system.Capabilities; national class MyANE extends EventDispatcher { tete-a-tete static volt-ampere _instance:MyANE; private var extCtx:ExtensionContext; semipublic function MyANE(objective:IEventDispatcher=zip) { if (!_instance) { if (this.isSupported) { extCtx = ExtensionContext.createExtensionContext("my.impressive.native.extension", null); if (extCtx != zip) { trace('[MyANE.AS3] extCtx is okay'); } else { line('[MyANE.AS3] extCtx is null.'); } } _instance = this; } other { throw Wrongdoing('[MyANE.AS3] This is a singleton, use getInstance, do non call the builder directly'); } } public function amaze isSupported():Boolean { paying back Capabilities.manufacturer.indexOf('Mac') > -1; } public static function getInstance():MyANE { return _instance != null ? _instance : new MyANE(); } public function init():void { extCtx.call("initLibrary"); } }
Part three. Library forum
Finally, we have 2 pieces of the native library. All you need is to connect them into a full-fledged ANE.
First, we need a handle in which we describe our extension. It will be the following * .xml file:
my.awesome.native.extension 1.0.0 MyANE.framework MyAwesomeNativeExtensionInitializer MyAwesomeNativeExtensionFinalizer
Here:
id - id of the resolver, which moldiness match the id that we specified when creating the context example in the as3 take off.
nativeLibrary is a compiled framework from the Verifiable-C
initializer, finalizer is the initializer and finalizer of the library (non circumstance), which was besides described in the Ojbective-C part.
IT is also suggested to build an implementation for the default platform, in which there is no native code. Well, follow the recommendations, it is not difficult.
The last piece of our library is in order, and forthwith we can get to build. And present the playfulness begins.
For convenience, I would apprise you to create a separate leaflet for the assembly, otherwise at that place will simply be confusion and porridge, which is already enough here. I use the following folder structure:
where
- _out - the de facto folder for the assembly.
- nonpayment - default implementation for the platform
- library.sfw - swf obtained by unzipping the assembled as3-part
- mac - effectuation for the mac program
- library.sfw - swf obtained aside unzipping the assembled as3-part
- MyANE.framework - a compiled Objective-C start out
- extension.xml - extension descriptor
- MakeANE.sh is just a script for quickly building a library
- nonpayment - default implementation for the platform
- ActionScript3 and Objective-C are project parts folders for the library.
Severally by depository library.sfw. Yes, this is a piece of a piece of the library, which should be separate, but at the same time, the assembled as3-piece is also needful for us. To cotton on, you necessitate to unzip the built as3 library as a full-time null archive (conserving this same as3 library).
Now all we need to do is build the extension using the AIR Developer Tool (ADT). You can uncovering it Hera: ../AIR_FOLDER/bin/adt
For assembly, I use the shadowing script (from the _out folder):
AIR_FOLDER / bin / adt -package -fair game ane MyANE.ane extension.xml -swc ../ActionSript3/bin/ MyANE.swc -platform MacOS-x86 -C mac. -program nonpayment -C default.
Now we have a finished MyANE.ane file, which is a compiled endemic library. But even this is non the remnant. The real fun begins when we seek to use the native library in an OS X project. Again, in that respect are a lot of tutorials and various FAQs for iOS, merely as it sour out, for OS X it is necessary to perform other rituals with a tambourine, and not but.
The last part. Integration of the native library into the project
So, we have our own scripted program library. Here it is, the polished * .ane file out. Take and enjoyment. But no. In order to use the domestic library in OS X during development, it is not needed. But naturally, our efforts were non vainly. We just need to DO the following (I will delineate the process for IntelliJ Theme, but for Photoflash Builder the process is similar, in some cases even easier):
- Unzip the * .i file atomic number 3 a regular zilch archive into a leaflet that has the name exactly like the id of our denotation + .ane at the close. In our sheath, information technology will make up "my.awesome.native.reference.ane". It is better to copy this folder to a new directory inside the project. For example, I have this libs-ane, which already contains unzipped extensions.
- In IntelliJ Estimation, in the project settings, Brawl Non add this directory depending.
- In another directory inside the project, add the accumulated as3 library. I throw this directory called libs-swc.
- We already total this directory depending on the project. Link Type Merged.
- In the ADL startup options, you need to add the following option -extdir / ABSOLUTE_PATH_TO_PROJECT / libs-cardinal. In IntelliJ IDEA, these options are in Run-> Edit Configurations-> AIR Debug Launcher Options.
- In the project word form, add the id of the native extension in the "extensions" freeze
my.awesome.native.extension
Directly we can use native extensions for debugging. But in that location is ace more thing. Atomic number 3 you probably know, in the iOS SDK on that point are a number of classes that will merely work correctly when they are launched from the Finder. To do this, using the same IntelliJ Theme, you tin can build a native bundle and use it. But the problem is that the previous method of integrating the native reference will not allow America to build the bundle. But the assemblage can still be efficacious to us, so we need to work a little many. Remember our * .one? So right now its time has total.
- All * .ane mustiness equal added to the close separate directory, again in spite of appearanc the project. I have this folder called anes.
In IntelliJ Theme, in the project settings, we besides add this directory depending. The type of connection will become ANE and it is impossible to change it (that is wherefore IT is impossible to collect bundles and piece of work in debug mode at the same time). Far for debugging - we remove this directory from dependencies, for meeting place of a bundle - we add u. - But anyhow, we want anes to be an external library. To do this, I use an extra build-config.xml file, which describes additional make parameters. In this establish-config.xml, you need to specify the anes directory as the path of the external library. The simplest option mightiness look the like this:
16.0.0 23 ${flexlib}/libs/role player/{targetPlayerMajorVersion}.{targetPlayerMinorVersion}/playerglobal.swc anes accurate libs-swc
To use an additional build-config Indian file, you must add it in the project settings. Project Anatomical structure -> Additional compiler configuration file.Considerably, or plane simpler, there you can add a parametric quantity to the Extra compiling program options: "-external-subroutine library-path itinerary-element anes"
Now you prat amass the autochthonous pack. This is done simply by Build-> Box AIR Coating. As a target, I use * .app.
Wellspring, at the exit, we get a ready-made, domestic big mone, with a working draft that will use ANE.
That's altogether. Give thanks you for your tending, I hope this article is useful to someone. This is my first article on Habré, so I would enjoy to hear constructive criticism and advice on how to improve the clause. I will also in spades resolution questions in the comments, and, if possible, supplement the article.
If there is concern in this topic, then I would too like to talk of the interchange of various data betwixt as3 and the aboriginal code, nigh events and much more (although these are already more general concepts happening which it is a morsel easier to find selective information).
DOWNLOAD HERE
GET Developing Air Native Extensions (ANE) for OS X / Sudo Null IT News FREE
Posted by: villarrealafters.blogspot.com
0 Response to "GET Developing Air Native Extensions (ANE) for OS X / Sudo Null IT News FREE"
Post a Comment