gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Gnash-commit] gnash ChangeLog doc/C/extensions.xml


From: strk
Subject: Re: [Gnash-commit] gnash ChangeLog doc/C/extensions.xml
Date: Fri, 16 Feb 2007 09:29:35 +0100

On Fri, Feb 16, 2007 at 04:16:49AM +0000, Rob Savoye wrote:

> Added files:
>       doc/C          : extensions.xml 
> 

> +     // setup so DummyClass.func1() and DummyClass.func2() work from Flash.
> +     static void
> +     attachInterface(as_object *obj)
> +     {
> +            obj->set_member("func1", &ext_func1);
> +            obj->set_member("func2", &ext_func2);
> +     }
> +      </programlisting>

In latest changes we're  using 'init_member', rather then 'set_member'.
The difference is thats are:
        - init_member will convert the function name to lowercase
          if target SWF is < 7
        - init_member will *not* seek for getter-setter properties
          in the inheritance chain to set any of them instead
        - init_member will *not* specially thread __proto__
        - init_member will automatically set  member flags to
          dontDelete|dontEnum
Also, if NULL is an invalid argument I prefer to get an as_object& (reference)
rather then a pointer. This is already implemented in new classes (see 
xmlnode.cpp).


> +     static as_object*
> +     getInterface()
> +     {
> +         static boost::intrusive_ptr&lt;as_object&gt; o;
> +         if (o == NULL) {
> +             o = new as_object();
> +         }
> +         return o.get();
> +     }

Remember to call attachInterface(*o) right after creation, or
the interface will be empty.

> +     static void
> +     dummyext_ctor(const fn_call&amp; fn)
> +     {
> +         DummyExt *obj = new DummyExt();
> +
> +         attachInterface(obj);
> +         fn.result->set_as_object(obj); // will keep alive
> +     }
> +      </programlisting>

Here you're attaching the interface to the newly created object, while
it's usually more appropriate to let the interface be inherited from
the class. To do so, the DummyExt() class would derive from as_object
constructing it with the single parameter being the exported interface:

        class DummyExt: public as_object {
                DummyExt()
                        :
                        as_object(getInterface)
                {}
        }

This allows programmers to override a method, or to add a method
to the AS class which is automatically inherited by all instances of
that AS class.

> +     // Creates a new button with the label as the text.
> +     void func1(const fn_call&amp; fn)
> +     {
> +         DummyExt *ptr = dynamic_cast&lt;DummyExt *&gt;(fn.this_ptr);
> +         assert(ptr);
> +     
> +         if (fn.nargs > 0) {
> +             const char *label = fn.arg(0).to_string();
> +             bool ret = ptr->dummy_text_label(label);
> +             fn.result->set_bool(ret);
> +         }
> +     }

Assertign that the 'this' pointer of func1 call is a DummyExt is azardous.
Consider this:

        var dummy = new DummyExt;
        var str = new String;
        str.myFunc = dummy.func1;
        str.myFunc('Feel free to abort') ;

In the above example, the 'func1' member will be called with a string_as_object
as 'this' pointer. In order to have a common handling of these cases, new 
developments
are settling up to this kind of implementation:

        void func1(const fn_call& fn)
        {
                DummyExt *ptr = ensureDummyExt(fn.this_ptr);
                assert(ptr);
                ...
        }

The ensureDummyExt will throw an ActionException if the 'this' ptr is
NOT a DummyExt:

  static DummyExt*
  ensure_sound(as_object* obj)
  {
          DummyExt* ret = dynamic_cast<DummyExt*>(obj);
          if ( ! ret )
          {
                  throw ActionException("builtin method or gettersetter for 
DummyExt objects called against non-DummyExt instance");
          }
          return ret;
  }
        

--strk;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]