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