CVSROOT: /sources/gnash Module name: gnash Changes by: Sandro Santilli <strk> 07/12/18 22:05:14
Modified files: . : ChangeLog doc/C : extensions.xml Log message: gave a review of how to create extensions. Should be a currently correct way of doing it. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.5209&r2=1.5210 http://cvs.savannah.gnu.org/viewcvs/gnash/doc/C/extensions.xml?cvsroot=gnash&r1=1.4&r2=1.5 Patches: Index: ChangeLog =================================================================== RCS file: /sources/gnash/gnash/ChangeLog,v retrieving revision 1.5209 retrieving revision 1.5210 diff -u -b -r1.5209 -r1.5210 --- ChangeLog 18 Dec 2007 21:28:58 -0000 1.5209 +++ ChangeLog 18 Dec 2007 22:05:13 -0000 1.5210 @@ -1,5 +1,7 @@ 2007-12-18 Sandro Santilli <[EMAIL PROTECTED]> + * doc/C/extensions.xml: gave a review of how to create extensions. + Should be a currently correct way of doing it. * server/character.cpp (destroy): make sure to set the _unloaded flag to avoid leaks (Fixes bug #21842). Index: doc/C/extensions.xml =================================================================== RCS file: /sources/gnash/gnash/doc/C/extensions.xml,v retrieving revision 1.4 retrieving revision 1.5 diff -u -b -r1.4 -r1.5 --- doc/C/extensions.xml 18 May 2007 17:25:42 -0000 1.4 +++ doc/C/extensions.xml 18 Dec 2007 22:05:14 -0000 1.5 @@ -115,25 +115,27 @@ <emphasis>attachInterface</emphasis>, and this sets the other function callbacks for all the methods this class supports. The method callbacks are attached to the parent - class by using <emphasis>set_member()</emphasis> to set a C + class by using <emphasis>init_member()</emphasis> to set a C function pointer to the string value used in the Flash movie. </para> <programlisting> - // setup so DummyClass.func1() and DummyClass.func2() work from Flash. + // Attach DummyClass 'func1' and 'func2' methods to the given object static void - attachInterface(as_object *obj) + attachInterface(as_object& obj) { - obj->set_member("func1", &ext_func1); - obj->set_member("func2", &ext_func2); + obj.init_member("func1", &ext_func1); + obj.init_member("func2", &ext_func2); } </programlisting> <para> The second function is commonly called <emphasis>getInterface()</emphasis>, and this returns a - smart pointer to the new object. Gnash uses smart pointers for - all ActionScript class definitions. (and many other things) + pointer to a static prototype of the class. + Gnash uses garbage collection for ActionScript objects + so you need to register the static with the VM to give it + a chance to be marked as reachable. </para> <programlisting> static as_object* @@ -142,6 +144,8 @@ static boost::intrusive_ptr<as_object> o; if (o == NULL) { o = new as_object(); + VM::get().addStatic(o); + attachInterface(*o); } return o.get(); } @@ -155,25 +159,31 @@ <emphasis>func2</emphasis>. </para> <programlisting> - static void + static as_value dummyext_ctor(const fn_call& fn) { - DummyExt *obj = new DummyExt(); + DummyExt *obj = new DummyExt(); // will setup prototypes - attachInterface(obj); - fn.result->set_as_object(obj); // will keep alive + return as_value(obj); } </programlisting> <para> - Allocate the new object and return a smart pointer. + The trick for the above simple constructor to work is that + class appartenence is setup in the C++ DummyExt constructor + itself, which should derive from as_object and construct the + base passing it the interface (prototype) of it's class. </para> <programlisting> - std::auto_ptr<as_object> - init_dummyext_instance() + class DummyExt : public as_object { - return std::auto_ptr<as_object>(new DummyExt()); - } + public: + DummyExt() + : + as_object(getInterface()) // returns the static prototype + {} + + }; </programlisting> <para> @@ -190,18 +200,16 @@ void dummyext_class_init(as_object &obj) { - static boost::intrusive_ptr<builtin_function> cl; - if (cl == NULL) { + static builtin_function* cl=NULL; + if (!cl) + { + // Create a builtin function using the given constructor + // to instanciate objects and exporting the given interface cl = new builtin_function(&dummyext_ctor, getInterface()); - attachInterface(cl.get()); + VM::get().addStatic(cl); // will forbid to collect the class } - VM& vm = VM::get(); - std::string name = "DummyExt"; - if ( vm.getSWFVersion() < 7 ) { - boost::to_lower(name, vm.getLocale()); - } - obj.init_member(name, cl.get()); + obj.init_member("DummyExt", cl); } } // end of extern C </programlisting> @@ -216,15 +224,17 @@ </para> <programlisting> // Creates a new button with the label as the text. - void func1(const fn_call& fn) + as_value func1(const fn_call& fn) { - DummyExt *ptr = dynamic_cast<DummyExt *>(fn.this_ptr); - assert(ptr); + // Following line will ensure 'func1' is called for a DummyExt instance, + // or would throw an exception which should behave as if we returned the + // undefined value. + boost::intrusive_ptr<DummyExt> ptr = ensureType<DummyExt>(fn.this_ptr); if (fn.nargs > 0) { - const char *label = fn.arg(0).to_string(); + std::string label = fn.arg(0).to_string(); bool ret = ptr->dummy_text_label(label); - fn.result->set_bool(ret); + return as_value(ret); } } </programlisting> _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit