Tutorial: Flash and C++ Native Extension


Coding with C++

With the C++ project finally set up, it's time to start adding some code. We'll start with the NativeAdd.h file so open up that file and enter the code below.

#include "FlashRuntimeExtensions.h"

extern "C"
{
  __declspec(dllexport) void ExtInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet, FREContextFinalizer* ctxFinalizerToSet);

  __declspec(dllexport) void ExtFinalizer(void* extData);

  __declspec(dllexport) FREObject doAdd(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]);
}

As mentioned, I'm no authority on C++, but I'll do my best to explain the code above. First, the #include is comparable to the import statement in ActionScript. This tells the file to also use the FlashRuntimeExtensions.h file. The extern "C" line tells the compiler that we want the following block of code to be compiled C-style and not C++ style.

The command I'm least familiar with is the __declspec(dllexport) but I think it is safe to assume this essentially marks the following functions as exports from our dll; meaning they are visible to other applications that might use the dll.

Following the __declspec(dllexport), we define our function signatures. Unlike AS3, the return type comes first. It is followed by the function name and then the parameter list. The first two functions are for setting up and shutting down our Native Extension. The third function is the one that will handle the bulk of the work for us, doAdd. Note that in this header file, we are simply defining the function signatures, but not providing a function body. We will do that next in the NativeAdd.cpp file.

Open the NativeAdd.cpp file and enter the following functions. We'll go over each function one at a time, but first let's just make sure the file is all ready to go. At this point, make sure the file contains only the following code.

#include "NativeAdd.h"
#include <stdlib.h>

extern "C"
{

}

We're going to be adding all of our functions inside the extern "C" block and we'll start with our doAdd function.

FREObject doAdd(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) 
{
  int32_t one, two, sum;
  FREObject result;

  FREGetObjectAsInt32(argv[0], &one);
  FREGetObjectAsInt32(argv[1], &two);

  sum = one + two;

  FRENewObjectFromInt32(sum, &result);

  return result;
}

This is the function that is actually going to do the work for our extension and return our sum. To begin with, we declare a few variables of type int32_t. The next variable is an FREObject that will hold the result of our addition. The FRE types are how data is passed between Flash and C; I highly suggest checking out the Adobe documentation on working with the various types if you are going to be doing more of this on your own.

The next two function calls grab the data passed in by Flash, which comes in via the argv array, and stores it in our locally defined variables one and two. These represent the two numbers that will be added together. Next we do the actual addition and store the result in the sum variable. The last thing we need to do before returning the sum is to convert it into an FRE object that Flash can understand. The function FRENewObjectFromInt32 takes care of that for us and now we can return the result.

You may be wondering about the ampersands and asterisks if you aren't familiar with C coding. It has to do with the actual memory address of the variables and is quite beyond the scope of this tutorial, but if you're interested in learning more, you can read up on pointers on wikipedia.

The next couple of functions we define are not specified in our NativeAdd.h file, but they are necessary all the same.

void ContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctions, const FRENamedFunction** functions)
{
  *numFunctions = 1;
  FRENamedFunction* func = (FRENamedFunction*)malloc(sizeof(FRENamedFunction)*(*numFunctions));
	
  func[0].name = (const uint8_t*)"doAdd";
  func[0].functionData = NULL;
  func[0].function = &doAdd;

 *functions = func;
}

void ContextFinalizer(FREContext ctx) 
{
  return;
}

These methods deal with the ActionScript ExtensionContext object which we'll see when we get to the AS part of this tutorial. The first function is the initializer. First we tell it how many functions we will define, which in this case is just the 1, doAdd. Next we allocate memory for the function using malloc. After that we fill in some data regarding our function. We give it a name, set the data to NULL and then mark the address of our function. Lastly, we assign our FRENamedFunction pointer, func, to the passed in double-pointer functions. I don't have a good grasp on working with pointers so most of this I got from the Adobe docs.

The other function, the finalizer, doesn't really need to do anything so we keep it simple with nothing more than an empty return statement.

The last two functions we need to add are the ones we had declared in our .h file; the ExtInitializer and ExtFinalizer functions. The functions we covered above are responsible for dealing with the extension context object, while the ones below are for the actual extension itself.

void ExtInitializer(void** extData, FREContextInitializer* ctxInitializer, FREContextFinalizer* ctxFinalizer) 
{
  *ctxInitializer = &ContextInitializer;
  *ctxFinalizer   = &ContextFinalizer;
}

void ExtFinalizer(void* extData) 
{
  return;
}

Again, the finalizer here is simple so we'll focus on the ExtInitializer function. This function is actually pretty simple as well. All we're doing is telling the extension where to find the context initializer and finalizer functions - that's it.

Your NativeAdd.cpp file should look like this when it is completed.

// NativeAdd.cpp : Defines the exported functions for the DLL application.

#include "NativeAdd.h"
#include 

extern "C"
{
  FREObject doAdd(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) 
  {
    int32_t one, two, sum;
    FREObject result;

    FREGetObjectAsInt32(argv[0], &one);
    FREGetObjectAsInt32(argv[1], &two);

    sum = one + two;

    FRENewObjectFromInt32(sum, &result);

    return result;
  }

  void ContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctions, const FRENamedFunction** functions)
  {
    *numFunctions = 1;
    FRENamedFunction* func = (FRENamedFunction*)malloc(sizeof(FRENamedFunction)*(*numFunctions));
	
    func[0].name = (const uint8_t*)"doAdd";
    func[0].functionData = NULL;
    func[0].function = &doAdd;

    *functions = func;
  }

  void ContextFinalizer(FREContext ctx) 
  {
    return;
  }

  void ExtInitializer(void** extData, FREContextInitializer* ctxInitializer, FREContextFinalizer* ctxFinalizer) 
  {
    *ctxInitializer = &ContextInitializer;
    *ctxFinalizer   = &ContextFinalizer;
  }

  void ExtFinalizer(void* extData) 
  {
    return;
  }
}

You should now be able to successfully build the dll! You can find the NativeAdd.dll in either the debug or release folder in your project directory.

Pages: 1 2 3 4 5

Bookmark and Share

5 Responses to “Tutorial: Flash and C++ Native Extension”

  1. Impressive publish! STICK WITH IT!

  2. Khan says:

    Excellent tips. Good tutorial for c++.

  3. Tomasz Dysinski says:

    Excellent and thorough!

    I have a comment about the following command line:

    adt -package -target ane NativeAdd.ane extfiles/extdesc.xml -swc extfiles/com.yourname.NativeAdd.swc
    -platform Windows-x86 -C extfiles NativeAdd.dll library.swf

    You left the namespace in extfiles/com.yourname.NativeAdd.swc. I couldn’t get it to work until I removed the namespace part, but then again, I wrote a BAT file to run this from the bin folder instead of the extfiles folder in the flex SDK bin folder (more typing, but less chance of misplacing files).

    Anyways, thanks again for taking the time to write this.

  4. Rhuno says:

    There is a lot going on in this tutorial. I do plan on eventually trying to make a video tutorial for this as it may be easier to follow.

  5. Erik Forsstrom says:

    Thank you so much for taking your time and writing this great tutorial!

    If you have plans to create a .bat file for the AS3 side, this acompc compiler option helps alot
    -directory=true -output=destination_directory
    This saves you the step of unpacking the library.swf from the .swc
    Run the acompc twice, one for the .swc and one for the .swf

Leave a Reply

Subscribe to RSS feed FGS5 Badge