QueTwo's Blog

thouoghts on telecommunications, programming, education and technology

Tag Archives: MacOS

Working with AIR Native Extensions on the Mac

As I said in my previous blog post, creating the ArduinoConnector ANE for the MacOS X platform was frustrating.  It turns out that Apple ships a slightly modified version of GCC that is close to what is offered on the Linux/Unix and Windows platforms, but not 100% the same.  When I approached the project, I thought it would be a cake-walk — simply take CDT (or gcc command-line), and point it to my POSIX C code, and I should be a few clicks away from creating the .framework file needed for AIR.

Turns out that the only way to make a .framework file is by using Apple’s Xcode (unless I’m really missing something in the gcc man pages).  I wasn’t really in the mood to learn yet another coding IDE, but I did want to post some of the gotcha’s I found in creating the Mac version of the ANE.  These are not step-by-steps, but rather things that tripped me up.

  • When you create a new Xcode project, you must choose a Cocoa Framework project (under Framework & Library).
  • Add the “Adobe AIR.framework” by clicking on the project name, and then going to Add, Existing Frameworks.  The Adobe AIR Framework file is found in your “Flash Builder App Dir -> sdks -> 4.6.0 -> runtimes -> air -> mac”  folder.
  • The Adobe AIR Framework file auto-includes the header file, and the external library that you need to link to.  Don’t go searching for another header file, you don’t need it.
  • Create/Import your .c and .h files and attempt to compile before setting your project settings.  If you don’t try to compile before you set your project files, you won’t see 3/4 of the compiler settings you need to make things right.  This one threw me into a loop for at least a day.
  • All of the examples have you including the <Adobe AIR/Adobe AIR.h> file in your project — I found this works, but all it is doing is including the FlashRuntimeExtensions.h that exists within the Adobe AIR framework.  I decided to resist change and include the Adobe AIR.h file.  It works.
  • There are two places you need to set your compiler and project settings.  One is on the project itself (the top-most node in the Groups & Files tree), and the other is in the Targets -> ProjectName.framework node.  Set all settings in both places (they don’t cascade once it has been compiled once, which you have to do to get the GCC settings to show up right).
  • Make sure your project is compiling 32-bit frameworks, targeted to the 10.5 SDK.   I never found that documented anywhere, and it was sheer luck I tried those combos.
  • Make sure that you turn the optimization level to None (0).  If you don’t do this, things will seem to work, but if you use any of the FREGet or FRENew functions, they will produce seemingly random numbers (I was convinced it was passing me back pointers casted as integers, but who knows).
  • Make the following target and project settings changes that deviate from the defaults :
    • Architetures : 34-bit Universal
    • Base SDK : Mac OS X 10.5
    • Build Active Architecture Only – Checked
    • C/C++ Compiler Version : GCC 4.2
    • Linking Compatibility Version : 1
    • Linking Current Library Version : 1
    • Other Linker Flags : -flat_namespace -weak_Framework “Adobe AIR”
    • Runpath Search Paths :
      • @executable_path/../runtimes/air/mac
      • @executable_path/../Frameworks
      • /Library/Frameworks
    • Packaging Framework Version: A
    • Wrapper Extension : framework
    • Framework Search Paths :
      • /Applications/Adobe\ Flash\ Builder\ 4.6/sdks/4.6.0/runtimes/air/mac
    • Library Search Paths: /Library/Frameworks/Adobe\ AIR.framework/Versions/1.0
    • GCC 4.2, Generate Position-Dependent Code: Unchecked
    • Optimization Level : None [-O0]
    • Other C Flags : -fvisibility=hidden
    • Other C++ Flags:  -fvisibility=hidden
    • Precompile Prefix Header : checked
  • In order to export the proper function names for your initialization and finalization functions, prefix them with __attribute__((visibility(“default”)))

Once you are creating your .framework properly, you should be all set.  If you created truly POSIX or standard C code, there should be very little changes you should need to make your project work.

I do have to make one additional note about a bug people have been finding with Flash Builder 4.6, as it was released on 11/30.  If you are attempting to include an ANE into a project, the project will compile, but if you debug the project, it will complain that it can’t find the method name (not the initilizer or finalizer, but one of your other method names).  If you debug your project from ANT or the command line, it will work fine.  The work-around for this is the following steps :

  • Make sure you have ADL in your search path.  Edit the /etc/paths file and add a new line with /Applications/Adobe Flash Builder 4.6/sdks/4.6.0/bin
  • Create a new folder on your desktop, Document folder, or somewhere where you will find it.  Copy your .ANE into it.
  • Create a new folder within this folder, and name it MyTestANE.ane    (make sure to include the .ane — that is very important)
  • cd into that new .ane directory, and execute the following command :    unzip ..\ArduinoConnector.ane      (assuming you named your .ane ArduinoConnector.ane)
  • Go into the bin-debug folder of your project, and run the following command :    adl -profile extendedDesktop -extdir ~/Documents/Extensions/ Main-app.xml    assuming that the directory you created in the second step was named Extensions and was located in your Documents folder.
  • You can repeat the last step as often as you need with no additional work, assuming you don’t need to update your .ane.   If you need to attach the debugger / profiler , you can follow the steps outlined on this blog (but use about:blank instead of http://localhost)

Well, I think that is about it.  I hope I can help alleviate some of the frustration that I suffered for somebody else in working with all this :)

Connecting your Arduino to AIR using an AIR Native Extension

One of the things that has been bugging the the most when working with Arduinos and AIR is the fact that you needed some sort of proxy application running in order to allow the AIR (or Flash) application to talk to the Arduino.  You see, the Arduino only exposes a Serial port (via USB), and AIR is limited in this regard.  The way people have gotten around this so far is to have AIR create a TCP socket connection to some sort of Proxy application, which in turn opens the Serial port to the Arduino.  It works, and it works very well, however this is a separate application you have to ship, have the user configure, and run.  Heck, even me as the developer found this solution clumsy when demoing these solutions.

I finally decided to fix the problem and write an AIR Native Extension.  The AIR Native Extension (ANE) is a C based .DLL / .framework for the Windows/Mac platforms that allows AIR to essentially open a COM port.  I wrote it in a way that is supposed to emulate the functions of the flash.net.Socket library that is included in the AIR runtime.  I’ve posted the entire project, including the source code and final binaries on Google Code at http://code.google.com/p/as3-arduino-connector/ (well, everything except for my compilation scripts, which are specific to my computers). 

The biggest learning experience in creating this ANE was developing on the MacOS platform.  I’ve never done any programming targeted for that platform before, and working with XCode is just a pain.  I’m used to environments like Visual Studio and Eclipse, but XCode always seemed to fight me every step of the way.  From simple things like hiding all the project properties, to trying to force you into an MDI workflow.  Also, working with the lack of documentation on the AIR Runtime side was kind of depressing…  Don’t worry, a future blog post will try to fill everybody in on how to make an ANE using XCode.

Using the ANE :

  • Include the ANE into your project.  Make sure you are using Flash Builder 4.6 or later. Right-Click on your project in the Package Explorer (Project Explorer), and go to Properties.  Go to the Flex Build Path tab, and then the Native Extensions tab.  Click “Add ANE…” and bring it in.  It does not need to reside within your project source folder.
  • Next, import the com.quetwo.Arduino.ArduinoConnector and the com.quetwo.Arduino.ArduinoConnectorEvent packages.
  • Instantiate a new variable of type ArduinoConnector.
  • Check the isSupported() function to make sure that the ANE is supported on your specific platform, and if it loaded properly.
  • Call the getComPorts() function which will return an array of valid list of COM ports on your OS.  On Windows, this returns ALL COM ports that are valid in Windows, where on the MacOS platform, it will return any USB Serial Devices, which usually would only be your Arduino.
  • Make the connection to the Arduino by calling the connect(comPort, baud) function.  You will need to pass in one of the COM ports from the getComPorts() array, along with the baud rate that your Arduino is operating on.  If you are using Firmata, it is 57600.  Most other Arduino projects use 9600.
  • Next, add an event listener to listen for the “socketData” event.  This will fire when new data is available in the data buffer.  Don’t wait too long to pull data out of the buffer, because it is only 4k :)

Sending Data:

Sending data is just like the Socket class, except you don’t have to flush() the buffer — the data goes out in realtime.  The two most common ways to send data :

  • writeString(“hello world”);
  • writeByte(255);

Getting Data from the Buffer:

As data arrives and is placed into the buffer, the bytesAvailable variable is incremented to reflect how many bytes are available.  Most people will read data from the buffer using one of the two functions :

  • readBytesAsString();
  • readByte();

All of the read functions are FIFO, meaning they will return the oldest data in the buffer before they return the newest (First In, First Out).

On the Google Code site, I am posting more detailed documentation, including a simple patch to as3Glue which will allow as3Glue to work seamlessly with this ANE. 

Enjoy, and please provide feedback on this ANE.  It’s the first one I’ve released to the public and I’d like to know how it works for everybody!

Follow

Get every new post delivered to your Inbox.

Join 29 other followers