My favorites | Sign in
Logo
                
Search
for
Updated Jan 02, 2009 by zwetan
NativeClasses  
HOWTO work with Native Classes.

Introduction

A Native class is an AS3 implementation that is made in C/C++

see Changes to native classes, scripts, and methods

Recent changes to Tamarin added a new utility (nativegen.py) to
auto-generate the maps for native classes, methods, and scripts. It's
currently optional -- you can still use the old-style hand-coded native maps
-- but we want to move to requiring this as it will pave the way for future
optimizations, and as an added benefit, make your code simpler.

nativegen.py is run as a post-processing step for builtin abc's, and is
invoked after you compile with asc.jar. (Note that the .cpp and .h files
produced by asc.jar will be unused.) Just call it with the .abc file for
your natives:

    python ./utils/nativegen.py ./core/builtin.abc mynatives.abc

note you can specify multiple .abc's on the command line; only the last will
have the maps generated (the others are just used for importing and
resolving references).

The script will output two files, mynatives.cpp2 and mynatives.h2 -- this is
a bit silly, and will probably change in the future, but for now, just
rename them to .cpp and .h. Note that these replace the .cpp and .h files
produced by asc.jar!

Now you need to tweak your native classes a bit:

(1) wherever you currently call initNativeTables()/parseActionBlock(), this
gets replaced by

        pool = AVM_INIT_BUILTIN_ABC(Foo, core, NULL);

which calls a function that nativegen.py generated for you and replaces the
old giant mess.

(2) ensure that the BEGIN_NATIVE_SCRIPTS/BEGIN_NATIVE_CLASSES tables are
inside the avmplus::NativeID namespace.

(3) rebuild the native thunks with nativegen.py, but add -<nativemapname=Foo
to its command line, where "Foo" is actually whatever you pass as the
arguments to the BEGIN_NATIVE_SCRIPTS/BEGIN_NATIVE_CLASSES macro.

Now, you can start migrating to having nativegen.py generate the maps for
you. You can convert a single class at a time (which is handy if you have
hundreds of native classes and don't want to do everything in a single
pass). What you have to do:

(1) add metadata to the AS3 declaration for the class:

   [native(cls="FooClass", instance="FooObject", methods="auto")]
   public class Foo { ... }

Where "FooClass" is the name of the C++ class that implements the class
object for Foo, and "FooObject" is the name of the C++ class that implements
the instance of Foo. If you omit "cls", ClassClosure will be assumed. If you
omit "instance", ScriptObject will be assumed. (You can't omit both.) "auto"
is the only valid value for method at present.

A similar technique exists for native scripts, with the wrinkle that scripts
can't actually have metadata applied to them directly; the workaround is to
apply the metadata to a toplevel function, eg,

    package something
    {
        ...
        [native(script="SamplerScript", methods="auto")]
        public native function somefunction(obj:Object):Boolean;
    }

(Question: is anyone out there using native scripts? They're rarely used and
might be a candidate for deprecation, since they can generally be
approximated by wrapping native classes in pure AS3 code.)

(2) Check the names of the C++ methods that implement the native methods;
they now must match the names of the AS3 methods (ignoring namespaces and
access limits); getters/setters are prefixed with "get_" and "set_"
respectively.

There's one oddball exception to this, which is that override methods are
prefixed with their AS3 classname, e.g.

    class Base { native function foo():void; }
    class Child extends Base { override native function foo():void; }

This would end up expecting C++ classes like

    class BaseObject : public ScriptObject { void foo(); }
    class ChildObject : public BaseObject { void Child_foo(); }

Admittedly, this is pretty horrible... the intent was avoid ambiguous
references, but it's not clear if it's actually a problem in practice.
Opinions welcomed here.

(4) delete the classes entry from the BEGIN_NATIVE_SCRIPTS or
BEGIN_NATIVE_CLASSES table.

(5) delete the entire BEGIN_NATIVE_MAP table for the class or script.

Once you've converted all your native classes to autogenerated maps, you
should stop passing --nativemapname as an argument to nativegen.py, as it
generates extra code that won't be necessary. (The --nativemapname option
will go away in a future revision to Tamarin.)

Details

Since redtamarin 0.2 we use only autogenerated maps.

Also, we try to change as few as possible the source code from Tamarin and here how to do it:

in src/extensions/MyClass.as
...
package whatever
{
    [native(cls="MyClass", methods="auto")]
    public class MyClass
    {
...

Sign in to add a comment
Hosted by Google Code