Home | History | Annotate | Download | only in php
      1 /*
      2   Implement a more natural wrap for factory methods, for example, if
      3   you have:
      4 
      5   ----  geometry.h --------
      6        struct Geometry {
      7          enum GeomType{
      8            POINT,
      9            CIRCLE
     10          };
     11 
     12          virtual ~Geometry() {}
     13          virtual int draw() = 0;
     14 
     15 	 //
     16 	 // Factory method for all the Geometry objects
     17 	 //
     18          static Geometry *create(GeomType i);
     19        };
     20 
     21        struct Point : Geometry  {
     22          int draw() { return 1; }
     23          double width() { return 1.0; }
     24        };
     25 
     26        struct Circle : Geometry  {
     27          int draw() { return 2; }
     28          double radius() { return 1.5; }
     29        };
     30 
     31        //
     32        // Factory method for all the Geometry objects
     33        //
     34        Geometry *Geometry::create(GeomType type) {
     35          switch (type) {
     36          case POINT: return new Point();
     37          case CIRCLE: return new Circle();
     38          default: return 0;
     39          }
     40        }
     41   ----  geometry.h --------
     42 
     43 
     44   You can use the %factory with the Geometry::create method as follows:
     45 
     46     %newobject Geometry::create;
     47     %factory(Geometry *Geometry::create, Point, Circle);
     48     %include "geometry.h"
     49 
     50   and Geometry::create will return a 'Point' or 'Circle' instance
     51   instead of the plain 'Geometry' type. For example, in python:
     52 
     53     circle = Geometry.create(Geometry.CIRCLE)
     54     r = circle.radius()
     55 
     56   where circle is a Circle proxy instance.
     57 
     58   NOTES: remember to fully qualify all the type names and don't
     59   use %factory inside a namespace declaration, ie, instead of
     60 
     61      namespace Foo {
     62        %factory(Geometry *Geometry::create, Point, Circle);
     63      }
     64 
     65   use
     66 
     67      %factory(Foo::Geometry *Foo::Geometry::create, Foo::Point,  Foo::Circle);
     68 
     69 
     70 */
     71 
     72 /* for loop for macro with one argument */
     73 %define %_formacro_1(macro, arg1,...)macro(arg1)
     74 #if #__VA_ARGS__ != "__fordone__"
     75 %_formacro_1(macro, __VA_ARGS__)
     76 #endif
     77 %enddef
     78 
     79 /* for loop for macro with one argument */
     80 %define %formacro_1(macro,...)%_formacro_1(macro,__VA_ARGS__,__fordone__)%enddef
     81 %define %formacro(macro,...)%_formacro_1(macro,__VA_ARGS__,__fordone__)%enddef
     82 
     83 /* for loop for macro with two arguments */
     84 %define %_formacro_2(macro, arg1, arg2, ...)macro(arg1, arg2)
     85 #if #__VA_ARGS__ != "__fordone__"
     86 %_formacro_2(macro, __VA_ARGS__)
     87 #endif
     88 %enddef
     89 
     90 /* for loop for macro with two arguments */
     91 %define %formacro_2(macro,...)%_formacro_2(macro, __VA_ARGS__, __fordone__)%enddef
     92 
     93 %define %_factory_dispatch(Type)
     94 if (!dcast) {
     95   Type *dobj = dynamic_cast<Type *>($1);
     96   if (dobj) {
     97     dcast = 1;
     98     SWIG_SetPointerZval(return_value, SWIG_as_voidptr(dobj),$descriptor(Type *), $owner);
     99   }
    100 }%enddef
    101 
    102 %define %factory(Method,Types...)
    103 %typemap(out) Method {
    104   int dcast = 0;
    105   %formacro(%_factory_dispatch, Types)
    106   if (!dcast) {
    107     SWIG_SetPointerZval(return_value, SWIG_as_voidptr($1),$descriptor, $owner);
    108   }
    109 }%enddef
    110