Welcome to the first tutorial of the Translating between ActionScript and Objective-C series.
Before we get on with data conversion, we need to have a word about how the ActionScript types are represented in the AIR C API, which is what you use when you make iOS Native Extensions for AIR.
Most of the data you will be passing around will be either an argument of a function you call or a result of a function you call.
When you implement a function on the native side which you want to be callable from ActionScript by doing
1 |
extensionContextInstance.call( “functionName”, argument_1, argument_2, ... ); |
your function needs to conform to the following signature:
1 2 |
FREObject functionName( FREContext ctx, void* funcData, uint32_t argc, FREObject argv[] ) |
You are already familiar with this signature from our post Communication between ActionScript and native code in an ANE. Click on the link if you need a reminder.
The interesting thing here is FREObject, which we see in a couple of places:
- Arguments to the function arrive as an array of FREObject instances: this is whatFREObject argv[] signifies.
- The function is expected to return a FREObject as a result.
If you open FlashRuntimeExtensions.h and look for the definition of FREObject, this is what you see:
1 |
typedef void * FREObject; |
What is void*?
This essentially means that FREObject is a void pointer. A pointer is a variable that holds a memory address. It can hold the memory address of something you expect to be of a particular type, for example:
1 |
int * pointerToInt; |
Or it can hold a memory address of data which can be of any type and the type is not specified when the pointer is declared:
1 |
void * pointerToAnyType; |
When you read the data located at the memory address which pointerToAnyType points to, you can interpret it as an int, as a string or as something else.
When you pass data from ActionScript to Objective-C, you can put pretty much anything in your list of arguments:
1 2 3 |
var argument_1 : int = 2; var argument_2 : String = “How you doin’?”; extensionContextInstance.call( “functionName”, argument_1, argument_2, ... ); |
Both of these will arrive at the C side as FREObject, in other words as void *.
How does void* help with AIR data types?
The Adobe AIR C API gives you convenience functions that help convert a FREObject into the native type you expect. You can find a full list here.
To get the integer value out of the first argument, for example, you will need to do the following:
1 2 3 4 5 6 7 8 |
int32_t nativeInt = 0; FREResult success = FREGetObjectAsInt32( argv[ 0 ], &nativeInt ); // FREResult is an enumerator which tells us whether the call succeeded. // It may fail because argv[ 0 ] was not the type we expected, // was not supplied by ActionScript at all, // we made the call on the wrong thread, etc. if ( FRE_OK == success ) { // we've got the int value successfully } |
Getting an Objective-C NSString out of the second argument requires a little more work:
1 2 3 4 5 6 7 8 9 |
uint32_t strLength = 0; const uint8_t * strValue = NULL; // This call gives us a pointer to a C-style string (an array of 8-bit characters) // and how long it is: FREResult success = FREGetObjectAsUTF8( argv[ 1 ], &strLength, &strValue ); // If all went well with the previous call, // we can try and convert the C-style string to an Objective-C NSString object: NSString * nativeString = NULL; if ( ( FRE_OK == success ) && ( 0 < strLength ) && ( NULL != strValue ) ) { nativeString = [ NSString stringWithUTF8String: ( const char * ) strValue ]; } |
Dealing with image data pointed to by a FREObject involves even more elaborate checks and conversions.
You can see how the work stacks up. Instead of adding six lines of code every time you want to read a string argument, how about making it a one-liner:
1 |
NSString * value = getNSStringFromFREObject( objectAS ); |
This is what you are going to build over the next posts in this series: your own little library of one-liner helper functions that will be at your fingertips to save you time with any iOS ANE project.
What’s next?
We start our conversion library with a few auxiliary functions.
Leave a Reply