Skip to main content
Participant
May 22, 2013
Question

Problems with C++ native extension for Android

  • May 22, 2013
  • 2 replies
  • 2258 views

Hello!

I'm trying to build sample native extension written with C++ on Android device.

But I have some troubles caused by the error #3500.

What I have:

1) Code of native library;

#include "FlashRuntimeExtensions.h"

#include <stdint.h>

#include <stdlib.h>

#include <string.h>

FREObject nativeFunction(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])

{

          uint32_t length = 12;

          const uint8_t* value = (const uint8_t*)"Hello from C";

 

          FREObject retObject;

          int res = FRENewObjectFromUTF8(length, value, &retObject);

          if (res == FRE_OK) {

                    return retObject;

          } else {

                    return NULL;

          }

}

void ContextInitializer(void *extData, const uint8_t *ctxType, FREContext ctx,

                        uint32_t *numFunctionsToSet,

                        const FRENamedFunction **functionsToSet)

{

          FRENamedFunction* func = (FRENamedFunction*)malloc(sizeof(FRENamedFunction)*1);

          func[0].name = (const uint8_t*)"nativeFunction";

          func[0].functionData = NULL;

          func[0].function = &nativeFunction;

  *functionsToSet = func;

}

void ContextFinalizer(FREContext ctx)

{

          return;

}

void NativeCppExtensionInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet,

                                   FREContextFinalizer* ctxFinalizerToSet)

{

  extDataToSet = NULL;

  *ctxInitializerToSet = ContextInitializer;

  *ctxFinalizerToSet = ContextFinalizer;

}

void NativeCppExtensionFinalizer(void* extData)

{

          return;

}

2) ActionScript library with Extension class:

package com.adobe.cppnativeextension

{

    import flash.external.ExtensionContext;

    public class CppNativeExtension

    {

        private static var context:ExtensionContext;

       

        public static function init():void {

            if (!context) {

                context = ExtensionContext.createExtensionContext('com.adobe.nativecpp', '');

            }

        }

       

        public static function nativeFunction():String {

            if (context != null) {

                return context.call('nativeFunction') as String;

            }

            return null;

        }

       

    }

}

3) Test mobile application:

<?xml version="1.0" encoding="utf-8"?>

<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"

        xmlns:s="library://ns.adobe.com/flex/spark" title="Home">

   

    <fx:Script>

        <![CDATA[

            import com.adobe.cppnativeextension.CppNativeExtension;

           

            public function button1_clickHandler(event:MouseEvent):void

            {

                CppNativeExtension.init();

                var res:String = CppNativeExtension.nativeFunction();

                btn1.label = res;

            }

        ]]>

    </fx:Script>

    <s:Button id="btn1" x="25" y="27" label="Launch native function" click="button1_clickHandler(event)"/>

   

</s:View>

My application.xml file looks like:

<extension xmlns="http://ns.adobe.com/air/extension/3.1">

          <id>com.adobe.nativecpp</id>

          <versionNumber>1</versionNumber>

          <platforms>

                    <platform name="Android-ARM">

                              <applicationDeployment>

                                        <nativeLibrary>libnativecpp.so</nativeLibrary>

                                        <initializer>NativeCppExtensionInitializer</initializer>

                                        <finalizer>NativeCppExtensionFinalizer</finalizer>

                              </applicationDeployment>

                    </platform>

          </platforms>

</extension>

Native library libnativecpp.so is built with Android NDK for Windows for ARM architecture.

After building ANE archive has such structure:

-- META-INF

------ ANE

---------- Android-ARM

-------------- libnativecpp.so

-------------- library.swf

---------- extension.xml

-- mimetype

-- catalog.xml

-- library.swf

After launching of mobile app in debug mode I receive such error:

ArgumentError: Error #3500: The extension context does not have a method with the name nativeFunction.

What did I do wrong?

Thanks for help in advance.


This topic has been closed for replies.

2 replies

Known Participant
September 11, 2014

I'm having a similar problem. The ANE works perfectly for Mac/Win and iOS, but not Android. When built for Android, it fails at the first call to a function that *should* be in the context.

In my case, I'm also including FlashRuntimeExtensions.so in the ANE package along with some external shared objects. Per the documentation, all the third-party objects are located in the ANE at META-INF/ANE/Android-ARM/libs/armeabi-v7a/*.so

There are absolutely zero errors in any logs prior to the #3500 error.

Is Android mangling C strings or something? Presumably this is an indicator that the function name isn't in the FRENamedFunctions array returned from the context initializer, since the context is created successfully.

Basic context initialization code looks like this:

extern "C" {

static FREObject initMyExtension(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]);

static FREObject someFunction(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]);

static FRENamedFunction named_functions[] = {

   { (uint8_t const * const)"initMyExtension", NULL, initMyExtension },

   { (uint8_t const * const)"someFunction", NULL, someFunction }

};

static uint32_t namedFunctionCount = sizeof(named_functions) / sizeof(FRENamedFunction);

void myContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctions, const FRENamedFunction** functions) {

    *numFunctions = namedFunctionCount;

    *functions = named_functions;

}

void myConextFinalizer(void* extData) {

}

void myExtensionInitializer(void** extData, FREContextInitializer* ctxInitializer, FREContextFinalizer* ctxFinalizer) {

    *ctxInitializer = &myContextInitializer;

    *ctxFinalizer = &myContextFinalizer;

}

}

Known Participant
May 22, 2013

In ContextInitializer you need to have:

*numFunctionsToTest = 1;

Participant
May 22, 2013

No, it doesn't work. Same error.

Is the ANE bundle structure correct?

Known Participant
May 23, 2013

The bundle structure seems to be fine. You would be getting an exception when creating the extension (ExtensionContext.createExtensionContext) if there was anything wrong with the bundle structure.

Can't see any problems with the code. I usually use Java for Android extensions. So maybe there are some specifics with using C++.