Upstream version 1.3.40
[profile/ivi/swig.git] / Lib / php / factory.i
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