Skip navigation
Currently Being Moderated

Pass C++ Class Member Function as a callable function in AIR Native Extension

May 3, 2012 11:48 AM

Tags: #c++ #c++_runtime_error #air_native_extensions

I'm writing an ANE and I'd like to know if anyone has been able to pass a C++ class member function pointer as a callable function from AIR? I have tried this so far with a little bit of C++11 trickery and it's crashing. I've also statically linked the libstdc++ into my library, according to the documentation, in order to ensure that these features I use work correctly. I have code like so:

 

 

FakeWorld* world = new FakeWorld();
*numFunctions = 1;
 
 
memberFunctions = (FRENamedFunction*) malloc(sizeof(FRENamedFunction) * (*numFunctions));
 
 
ANEMemberFunction mCreateFakeBody = std::tr1::bind(&FakeWorld::createFakeBody, world, std::tr1::placeholders::_1, std::tr1::placeholders::_2, std::tr1::placeholders::_3, std::tr1::placeholders::_4);
ANEFunction* createFakeBody = mCreateFakeBody.target<ANEFunction>();
memberFunctions[0].name = (const uint8_t*) "createFakeBody";
memberFunctions[0].functionData = NULL;
memberFunctions[0].function = createFakeBody;
 
 
FRESetContextNativeData(ctx, (void*)world);
 


I just realized I'm using C here for allocating the member functions array.. silly me, but I don't think this is the cause of my issue. I refuse to believe that Adobe has built to the Native Extensions portion of the runtime in such a way that I have to cram every single function I want to create (natively) into a global, C formatted namespace (Especially since the documentation says that C is only required for the extenion and context initializing function interfacing and the rest of the code can be done in C++ or objective-C). So please let me know if and how this is possible and I thank you so much in advance for your time!P.

 

P.S. Currently when I run this code, I can do the object initialization just fine. As soon as I invoke the "createFakeBody" method on the native side, the runtime dies and simply says:

 

Problem signature:
  Problem Event Name: BEX
  Application Name: adl.exe
  Application Version: 3.1.0.4880
  Application Timestamp: 4eb7612e
  Fault Module Name: StackHash_0a9e
  Fault Module Version: 0.0.0.0
  Fault Module Timestamp: 00000000
  Exception Offset: 00000000
  Exception Code: c0000005
  Exception Data: 00000008
  OS Version: 6.1.7601.2.1.0.256.48
  Locale ID: 1033
  Additional Information 1: 0a9e
  Additional Information 2: 0a9e372d3b4ad19135b953a78882e789
  Additional Information 3: 0a9e
  Additional Information 4: 0a9e372d3b4ad19135b953a78882e789


Read our privacy statement online:
  http://go.microsoft.com/fwlink/?linkid=104288&clcid=0x0409


If the online privacy statement is not available, please read our privacy statement offline:
  C:\Windows\system32\en-US\erofflps.txt

 

Thanks again for your assitance.

 
Replies
  • Currently Being Moderated
    May 6, 2012 6:00 PM   in reply to Jesse Nicholson

    It's been a little while since i've dealt with C++ and not up to speed on tr1 or C++0x, so forgive me if i'm not helping.

     

    The the examples of std::tr1::bind that i'm seeing out there seem to be either dereferencing the bound 'this' pointer when creating the bound method, i.e. in your case *world instead of world, or using std::tr1::ref(*world), therefore i believe that bind expects the bound parameters to be passed by reference.

     

    Given that the result of std::tr1::bind is callable (basing that on http://stackoverflow.com/questions/3678884/virtual-member-functions-an d-stdtr1function-how-does-this-work) could you simplify to the following:


    memberFunctions[0].name = (const uint8_t*) "createFakeBody";
    memberFunctions[0].functionData = NULL;
    memberFunctions[0].function = std::tr1::bind(&FakeWorld::createFakeBody, *world, std::tr1::placeholders::_1, std::tr1::placeholders::_2, std::tr1::placeholders::_3, std::tr1::placeholders::_4);

     

    Or for an even simpler starting point, creating a test member function 'helloWorld' in FakeWorld that takes no arguments and using:

     

    memberFunctions[0].name = (const uint8_t*) "helloWorld";

    memberFunctions[0].functionData = NULL;

    memberFunctions[0].function = std::tr1::bind(&FakeWorld::helloWorld, *world);

     

    Hope this helps.

     
    |
    Mark as:
  • Currently Being Moderated
    Jun 7, 2012 9:52 PM   in reply to Jesse Nicholson

    Hey thanks for the followup. Great project - i'll definitely check it out if I ever put aside time to work on 'that game idea'

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points