Changeset 28
- Timestamp:
- 07/12/06 19:24:58 (2 years ago)
- Files:
-
- trunk/dcompiler.py (modified) (1 diff)
- trunk/examples/testdll/testdll.d (modified) (2 diffs)
- trunk/infrastructure/pyd/class_wrap.d (modified) (6 diffs)
- trunk/infrastructure/pyd/ctor_wrap.d (modified) (2 diffs)
- trunk/infrastructure/pyd/def.d (modified) (1 diff)
- trunk/infrastructure/pyd/ftype.d (modified) (2 diffs)
- trunk/infrastructure/pyd/func_wrap.d (modified) (5 diffs)
- trunk/infrastructure/pyd/generators/readme.txt (added)
- trunk/infrastructure/pyd/generators/tuple.py (added)
- trunk/infrastructure/pyd/generators/tuple.txt (added)
- trunk/infrastructure/pyd/op_wrap.d (modified) (1 diff)
- trunk/infrastructure/pyd/pyd.d (modified) (1 diff)
- trunk/infrastructure/pyd/tuples.d (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/dcompiler.py
r26 r28 36 36 'op_wrap.d', 37 37 'pyd.d', 38 'tuples.d', 38 39 ] 39 40 trunk/examples/testdll/testdll.d
r27 r28 3 3 import python; 4 4 import pyd.pyd; 5 //import pyd.ftype; 5 6 import std.stdio; 6 7 7 // d_type testing 8 void apply_test(int i, char[] s) { 9 writefln("%s %s", i, s); 10 } 11 8 12 void foo() { 9 PyObject* s = PyString_FromString("blargh"); 10 PyObject* i = PyInt_FromLong(20); 11 12 int a = d_type!(int)(i); 13 char[] b = d_type!(char[])(s); 14 15 writefln("%s\n%s", a, b); 16 17 Py_DECREF(s); 18 Py_DECREF(i); 13 alias tuple!(int, char[]) Tuple; 14 // alias dg_from_tuple!(void, Tuple) dg; 15 Tuple t; 16 // Tuple.TypeNo!(0) i = 20; 17 // typeof(Tuple.arg1) j = 30; 18 t.arg1 = 20; 19 t.arg2 = "Monkey"; 20 // t.arg3 = 5.8; 21 apply_tuple_to_fn(t, &apply_test); 22 23 // writefln(typeid(ArgType!(dg, 1))); 24 // writefln(typeid(TypeNo!(Tuple, 0))); 25 // writefln(typeid(Tuple.A1)); 26 // writefln(typeid(dg)); 27 // writefln(i, " ", j); 19 28 } 20 29 … … 90 99 extern (C) 91 100 export void inittestdll() { 101 def!(foo, "foo"); 102 // Python does not support function overloading. This allows us to wrap 103 // an overloading function under a different name. Note that if the 104 // overload accepts a different number of minimum arguments, that number 105 // must be specified. 106 def!(foo, "foo2", void function(int), 1); 107 def!(bar, "bar"); 108 // Default argument support - Now implicit! 109 def!(baz, "baz"); 110 def!(spam, "spam"); 111 def!(iter_test, "iter_test"); 112 def!(func_test, "func_test"); 113 def!(dg_test, "dg_test"); 114 92 115 module_init("testdll"); 93 116 94 def!("foo", foo); 95 // Python does not support function overloading. This allows us to wrap 96 // an overloading function under a different name. 97 def!("foo2", foo, 1, void function(int)); 98 def!("bar", bar); 99 // Default argument support - Now implicit! 100 def!("baz", baz); 101 def!("spam", spam); 102 def!("iter_test", iter_test); 103 def!("func_test", func_test); 104 def!("dg_test", dg_test); 117 auto t = func_range!(foo, 0)(); 118 alias typeof(t) Tu; 119 writefln(typeid(TypeNo!(Tu, 1))); 120 writefln(MIN_ARGS!(bar)); 105 121 106 wrapped_class!( "Foo", Foo) f;122 wrapped_class!(Foo, "Foo") f; 107 123 // Constructor wrapping 108 f.init!( ctor!(int), ctor!(int, int));124 f.init!(tuple!(int), tuple!(int, int)); 109 125 // Member function wrapping 110 f.def!( "foo", Foo.foo);126 f.def!(Foo.foo, "foo"); 111 127 // Property wrapping 112 f.prop!( "i", Foo.i);128 f.prop!(Foo.i, "i"); 113 129 finalize_class(f); 114 130 } trunk/infrastructure/pyd/class_wrap.d
r27 r28 30 30 private import pyd.make_object; 31 31 private import pyd.op_wrap; 32 private import pyd.tuples; 32 33 33 34 private import std.string; … … 235 236 * wrapping the specific parts of the class. 236 237 */ 237 template wrapped_class(char[] classname, T) { 238 template wrapped_class(T, char[] classname) { 239 pragma(msg, "wrapped_class: " ~ classname); 238 240 struct wrapped_class { 239 241 static const char[] _name = classname; … … 249 251 * if more than one function has the same name as this one. 250 252 */ 251 template def(char[] name, alias fn, uint MIN_ARGS = MIN_ARGS!(fn), fn_t=typeof(&fn)) { 253 template def(alias fn, char[] name, fn_t=typeof(&fn), uint MIN_ARGS = MIN_ARGS!(fn)) { 254 pragma(msg, "class.def: " ~ name); 252 255 static void def() { 253 256 static PyMethodDef empty = { null, null, 0, null }; … … 272 275 * RO = Whether this is a read-only property. 273 276 */ 274 template prop(char[] name, alias fn, bool RO=false) { 277 template prop(alias fn, char[] name, bool RO=false) { 278 pragma(msg, "class.prop: " ~ name); 275 279 static void prop() { 276 280 static PyGetSetDef empty = { null, null, null, null, null }; … … 304 308 * the same number of arguments. 305 309 */ 306 template init( alias C1=undefined, alias C2=undefined, alias C3=undefined, alias C4=undefined, alias C5=undefined, alias C6=undefined, alias C7=undefined, alias C8=undefined, alias C9=undefined, alias C10=undefined) {310 template init(C1=Void, C2=Void, C3=Void, C4=Void, C5=Void, C6=Void, C7=Void, C8=Void, C9=Void, C10=Void) { 307 311 static void init() { 308 312 wrapped_class_type!(T).tp_init = 309 &wrapped_ctors!(T, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10).init_func;313 &wrapped_ctors!(T, tuple!(C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)).init_func; 310 314 } 311 315 } … … 321 325 alias wrapped_class_type!(T) type; 322 326 const char[] name = CLS._name; 327 pragma(msg, "finalize_class: " ~ name); 323 328 324 329 assert(DPy_Module_p !is null, "Must initialize module before wrapping classes."); trunk/infrastructure/pyd/ctor_wrap.d
r25 r28 25 25 private import pyd.class_wrap; 26 26 private import pyd.exception; 27 private import pyd.func_wrap; 27 28 private import pyd.make_object; 28 29 /** 30 * This template defines the footprint of an individual constructor. 31 */ 32 template ctor(T1=void, T2=void, T3=void, T4=void, T5=void, T6=void, T7=void, T8=void, T9=void, T10=void) { 33 static if (!is(T10 == void)) 34 const uint ARGS = 10; 35 else static if(!is(T9 == void)) 36 const uint ARGS = 9; 37 else static if(!is(T8 == void)) 38 const uint ARGS = 8; 39 else static if(!is(T7 == void)) 40 const uint ARGS = 7; 41 else static if(!is(T6 == void)) 42 const uint ARGS = 6; 43 else static if(!is(T5 == void)) 44 const uint ARGS = 5; 45 else static if(!is(T4 == void)) 46 const uint ARGS = 4; 47 else static if(!is(T3 == void)) 48 const uint ARGS = 3; 49 else static if(!is(T2 == void)) 50 const uint ARGS = 2; 51 else static if(!is(T1 == void)) 52 const uint ARGS = 1; 53 else 54 const uint ARGS = 0; 55 alias T1 arg1; 56 alias T2 arg2; 57 alias T3 arg3; 58 alias T4 arg4; 59 alias T5 arg5; 60 alias T6 arg6; 61 alias T7 arg7; 62 alias T8 arg8; 63 alias T9 arg9; 64 alias T10 arg10; 29 private import pyd.tuples; 30 31 template outer(T) { 32 T call_ctor()() { 33 return new T(); 34 } 35 36 T call_ctor(T1)(T1 t1) { 37 return new T(t1); 38 } 39 40 T call_ctor(T1, T2)(T1 t1, T2 t2) { 41 return new T(t1, t2); 42 } 43 44 T call_ctor(T1, T2, T3)(T1 t1, T2 t2, T3 t3) { 45 return new T(t1, t2, t3); 46 } 47 48 T call_ctor(T1, T2, T3, T4)(T1 t1, T2 t2, T3 t3, T4 t4) { 49 return new T(t1, t2, t3, t4); 50 } 51 52 T call_ctor(T1, T2, T3, T4, T5)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { 53 return new T(t1, t2, t3, t4, t5); 54 } 55 56 T call_ctor(T1, T2, T3, T4, T5, T6)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { 57 return new T(t1, t2, t3, t4, t5, t6); 58 } 59 60 T call_ctor(T1, T2, T3, T4, T5, T6, T7)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) { 61 return new T(t1, t2, t3, t4, t5, t6, t7); 62 } 63 64 T call_ctor(T1, T2, T3, T4, T5, T6, T7, T8)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) { 65 return new T(t1, t2, t3, t4, t5, t6, t7, t8); 66 } 67 68 T call_ctor(T1, T2, T3, T4, T5, T6, T7, T8, T9)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9) { 69 return new T(t1, t2, t3, t4, t5, t6, t7, t8, t9); 70 } 71 72 T call_ctor(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10) { 73 return new T(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10); 74 } 65 75 } 66 76 67 struct dummy { } 68 alias ctor!(dummy) undefined; 69 70 // This template wraps an individual call to a constructor 71 template wrapped_ctor(T, alias Ctor) { 72 int wrapped_ctor(PyObject* self, PyObject* args, PyObject* kwds) { 77 // This template accepts a list of "ctor" templates and uses them to wrap a Python tp_init function. 78 template wrapped_ctors(T, Tuple) { 79 alias wrapped_class_object!(T) wrap_object; 80 const uint ARGS = Tuple.length; 81 extern(C) 82 int init_func(PyObject* self, PyObject* args, PyObject* kwds) { 83 int len = PyObject_Length(args); 84 85 try { 86 73 87 T t; 74 75 try { /* begin try */ 76 77 static if (Ctor.ARGS == 1) { 78 t = new T( 79 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)) 80 ); 81 } else static if (Ctor.ARGS == 2) { 82 t = new T( 83 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 84 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)) 85 ); 86 } else static if (Ctor.ARGS == 3) { 87 t = new T( 88 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 89 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 90 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)) 91 ); 92 } else static if (Ctor.ARGS == 4) { 93 t = new T( 94 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 95 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 96 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 97 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)) 98 ); 99 } else static if (Ctor.ARGS == 5) { 100 t = new T( 101 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 102 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 103 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 104 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)), 105 d_type!(Ctor.arg5)(PyTuple_GetItem(args, 4)) 106 ); 107 } else static if (Ctor.ARGS == 6) { 108 t = new T( 109 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 110 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 111 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 112 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)), 113 d_type!(Ctor.arg5)(PyTuple_GetItem(args, 4)), 114 d_type!(Ctor.arg6)(PyTuple_GetItem(args, 5)) 115 ); 116 } else static if (Ctor.ARGS == 7) { 117 t = new T( 118 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 119 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 120 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 121 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)), 122 d_type!(Ctor.arg5)(PyTuple_GetItem(args, 4)), 123 d_type!(Ctor.arg6)(PyTuple_GetItem(args, 5)), 124 d_type!(Ctor.arg7)(PyTuple_GetItem(args, 6)) 125 ); 126 } else static if (Ctor.ARGS == 8) { 127 t = new T( 128 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 129 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 130 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 131 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)), 132 d_type!(Ctor.arg5)(PyTuple_GetItem(args, 4)), 133 d_type!(Ctor.arg6)(PyTuple_GetItem(args, 5)), 134 d_type!(Ctor.arg7)(PyTuple_GetItem(args, 6)), 135 d_type!(Ctor.arg8)(PyTuple_GetItem(args, 7)) 136 ); 137 } else static if (Ctor.ARGS == 9) { 138 t = new T( 139 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 140 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 141 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 142 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)), 143 d_type!(Ctor.arg5)(PyTuple_GetItem(args, 4)), 144 d_type!(Ctor.arg6)(PyTuple_GetItem(args, 5)), 145 d_type!(Ctor.arg7)(PyTuple_GetItem(args, 6)), 146 d_type!(Ctor.arg8)(PyTuple_GetItem(args, 7)), 147 d_type!(Ctor.arg9)(PyTuple_GetItem(args, 8)) 148 ); 149 } else static if (Ctor.ARGS == 10) { 150 t = new T( 151 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 152 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 153 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 154 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)), 155 d_type!(Ctor.arg5)(PyTuple_GetItem(args, 4)), 156 d_type!(Ctor.arg6)(PyTuple_GetItem(args, 5)), 157 d_type!(Ctor.arg7)(PyTuple_GetItem(args, 6)), 158 d_type!(Ctor.arg8)(PyTuple_GetItem(args, 7)), 159 d_type!(Ctor.arg9)(PyTuple_GetItem(args, 8)), 160 d_type!(Ctor.arg10)(PyTuple_GetItem(args, 9)) 161 ); 162 } 88 // Default ctor 89 static if (is(typeof(new T))) { 90 if (len == 0) { 91 t = new T; 92 goto Done; 93 } 94 } 95 // We only match the first supplied ctor with the proper number of 96 // arguments. (Eventually, we'll do some more sophisticated matching, 97 // but this will do for now.) 98 static if (ARGS >= 1) { 99 if (len == TypeNo!(Tuple, 0).length) { 100 // This works thusly: 101 // 1) outer!(T).call_ctor is a series of template functions 102 // that call a constructor with its passed arguments, and 103 // return the new object. 104 // 2) instant_from_tuple is a template that instantiates a 105 // template with the types in the passed tuple type. By 106 // combining call_ctor with the selected tuple representing 107 // the best match of constructor, we can get something like 108 // a pointer to a constructor function. 109 // 3) This function pointer is sent off to py_call, which calls 110 // it with the PyTuple that args points to. 111 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 0) ) fn1; 112 t = py_call!(typeof(&fn1), PyObject) ( &fn1, args ); 113 goto Done; 114 } 115 } 116 static if (ARGS >= 2) { 117 if (len == TypeNo!(Tuple, 1).length) { 118 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 1) ) fn2; 119 t = py_call!(typeof(&fn2), PyObject) ( &fn2, args ); 120 goto Done; 121 } 122 } 123 static if (ARGS >= 3) { 124 if (len == TypeNo!(Tuple, 2).length) { 125 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 2) ) fn3; 126 t = py_call!(typeof(&fn3), PyObject) ( &fn3, args ); 127 goto Done; 128 } 129 } 130 static if (ARGS >= 4) { 131 if (len == TypeNo!(Tuple, 3).length) { 132 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 3) ) fn4; 133 t = py_call!(typeof(&fn4), PyObject) ( &fn4, args ); 134 goto Done; 135 } 136 } 137 static if (ARGS >= 5) { 138 if (len == TypeNo!(Tuple, 4).length) { 139 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 4) ) fn5; 140 t = py_call!(typeof(&fn5), PyObject) ( &fn5, args ); 141 goto Done; 142 } 143 } 144 static if (ARGS >= 6) { 145 if (len == TypeNo!(Tuple, 5).length) { 146 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 5) ) fn6; 147 t = py_call!(typeof(&fn6), PyObject) ( &fn6, args ); 148 goto Done; 149 } 150 } 151 static if (ARGS >= 7) { 152 if (len == TypeNo!(Tuple, 6).length) { 153 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 6) ) fn7; 154 t = py_call!(typeof(&fn7), PyObject) ( &fn7, args ); 155 goto Done; 156 } 157 } 158 static if (ARGS >= 8) { 159 if (len == TypeNo!(Tuple, 7).length) { 160 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 7) ) fn8; 161 t = py_call!(typeof(&fn8), PyObject) ( &fn8, args ); 162 goto Done; 163 } 164 } 165 static if (ARGS >= 9) { 166 if (len == TypeNo!(Tuple, 8).length) { 167 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 8) ) fn9; 168 t = py_call!(typeof(&fn9), PyObject) ( &fn9, args ); 169 goto Done; 170 } 171 } 172 static if (ARGS >= 10) { 173 if (len == TypeNo!(Tuple, 9).length) { 174 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 9) ) fn10; 175 t = py_call!(typeof(&fn10), PyObject) ( &fn10, args ); 176 goto Done; 177 } 178 } else { 179 PyErr_SetString(PyExc_TypeError, "Unsupported number of constructor arguments."); 180 return -1; 181 } 182 Done: 183 (cast(wrapped_class_object!(T)*)self).d_obj = t; 184 wrap_class_instances!(T)[t]++; 163 185 164 186 } /* end try */ … … 177 199 } 178 200 179 (cast(wrapped_class_object!(T)*)self).d_obj = t;180 wrap_class_instances!(T)[t] = 1;181 182 201 return 0; 183 202 } 184 203 } 185 204 186 // This template accepts a list of "ctor" templates and uses them to wrap a Python __init__ function.187 template wrapped_ctors(T, alias C1, alias C2, alias C3, alias C4, alias C5, alias C6, alias C7, alias C8, alias C9, alias C10) {188 alias wrapped_class_object!(T) wrap_object;189 static if (!is(C10.arg1 == dummy))190 const uint ARGS = 10;191 else static if(!is(C9.arg1 == dummy))192 const uint ARGS = 9;193 else static if(!is(C8.arg1 == dummy))194 const uint ARGS = 8;195 else static if(!is(C7.arg1 == dummy))196 const uint ARGS = 7;197 else static if(!is(C6.arg1 == dummy))198 const uint ARGS = 6;199 else static if(!is(C5.arg1 == dummy))200 const uint ARGS = 5;201 else static if(!is(C4.arg1 == dummy))202 const uint ARGS = 4;203 else static if(!is(C3.arg1 == dummy))204 const uint ARGS = 3;205 else static if(!is(C2.arg1 == dummy))206 const uint ARGS = 2;207 else static if(!is(C1.arg1 == dummy))208 const uint ARGS = 1;209 else210 const uint ARGS = 0;211 extern(C)212 int init_func(PyObject* self, PyObject* args, PyObject* kwds) {213 int len = PyObject_Length(args);214 // Default ctor215 static if (is(typeof(new T))) {216 if (len == 0) {217 T t = new T;218 (cast(wrap_object*)self).d_obj = t;219 wrap_class_instances!(T)[t] = 1;220 return 0;221 }222 }223 // We only match the first supplied ctor with the proper number of224 // arguments. (Eventually, we'll do some more sophisticated matching,225 // but this will do for now.)226 static if (ARGS >= 1) {227 if (len == C1.ARGS)228 return wrapped_ctor!(T, C1)(self, args, kwds);229 }230 static if (ARGS >= 2) {231 if (len == C2.ARGS)232 return wrapped_ctor!(T, C2)(self, args, kwds);233 }234 static if (ARGS >= 3) {235 if (len == C3.ARGS)236 return wrapped_ctor!(T, C3)(self, args, kwds);237 }238 static if (ARGS >= 4) {239 if (len == C4.ARGS)240 return wrapped_ctor!(T, C4)(self, args, kwds);241 }242 static if (ARGS >= 5) {243 if (len == C5.ARGS)244 return wrapped_ctor!(T, C5)(self, args, kwds);245 }246 static if (ARGS >= 6) {247 if (len == C6.ARGS)248 return wrapped_ctor!(T, C6)(self, args, kwds);249 }250 static if (ARGS >= 7) {251 if (len == C7.ARGS)252 return wrapped_ctor!(T, C7)(self, args, kwds);253 }254 static if (ARGS >= 8) {255 if (len == C8.ARGS)256 return wrapped_ctor!(T, C8)(self, args, kwds);257 }258 static if (ARGS >= 9) {259 if (len == C9.ARGS)260 return wrapped_ctor!(T, C9)(self, args, kwds);261 }262 static if (ARGS >= 10) {263 if (len == C10.ARGS)264 return wrapped_ctor!(T, C10)(self, args, kwds);265 }266 PyErr_SetString(PyExc_TypeError, "Unsupported number of constructor arguments.");267 return -1;268 }269 }270 trunk/infrastructure/pyd/def.d
r26 r28 77 77 *It's greater than 10!) 78 78 */ 79 template def(char[] name, alias fn, uint MIN_ARGS = MIN_ARGS!(fn), fn_t=typeof(&fn)) { 79 template def(alias fn, char[] name, fn_t=typeof(&fn), uint MIN_ARGS = MIN_ARGS!(fn)) { 80 pragma(msg, "def: " ~ name); 80 81 void def() { 81 fn_t fptr = &fn; 82 PyObject* func = DPyFunc_FromDG!(fn_t, MIN_ARGS)(fptr); 83 PyObject_SetAttrString(DPy_Module_p, name ~ \0, func); 84 Py_DECREF(func); 82 PyMethodDef empty; 83 alias module_global_methods list; 84 85 list[length-1].ml_name = name ~ \0; 86 list[length-1].ml_meth = &func_wrap!(fn, MIN_ARGS, void, fn_t).func; 87 list[length-1].ml_flags = METH_VARARGS; 88 list[length-1].ml_doc = ""; 89 list ~= empty; 85 90 } 86 91 } trunk/infrastructure/pyd/ftype.d
r26 r28 149 149 { 150 150 private Tf fptr; 151 //pragma(msg, Tf); 151 152 static if( is( typeof(*Tf) U == function ) ) 152 153 alias U type; … … 599 600 /** 600 601 * This template will attempt to determine the minimum number of arguments a 601 * function can accept. (Written by Kirk McDonald.) Note that this accepts an 602 * alias parameter rather than a function pointer type, as the function and 603 * delegate types contain no information about default arguments. 602 * function can accept. Note that this accepts an alias parameter rather than a 603 * function pointer type, as the function and delegate types contain no 604 * information about default arguments. 605 * 606 * (Written by Kirk McDonald.) 604 607 */ 605 608 public trunk/infrastructure/pyd/func_wrap.d
r27 r28 29 29 private import pyd.ftype; 30 30 private import pyd.make_object; 31 private import pyd.tuples; 31 32 32 33 private import std.string; 33 34 34 35 // Builds a Python callable object from a delegate or function pointer. 35 template DPyFunc_FromDG(T, uint MIN_ARGS=NumberOfArgs!(T) , C=void) {36 template DPyFunc_FromDG(T, uint MIN_ARGS=NumberOfArgs!(T)) { 36 37 PyObject* DPyFunc_FromDG(T dg) { 37 38 alias wrapped_class_type!(T) type; … … 41 42 type.tp_basicsize = obj.sizeof; 42 43 type.tp_name = "DPyFunc"; 43 type.tp_call = &wrapped_func_call!(T , MIN_ARGS, C).call;44 type.tp_call = &wrapped_func_call!(T/*, MIN_ARGS*/).call; 44 45 PyType_Ready(&type); 45 46 is_wrapped!(T) = true; … … 53 54 } 54 55 55 template wrapped_func_call(fn_t, uint MIN_ARGS, C=void) { 56 // Calls the passed function with the passed Python tuple. 57 ReturnType!(fn_t) py_call(fn_t, PY)(fn_t fn, PY* args) { 58 const uint MAX_ARGS = NumberOfArgs!(fn_t); 59 alias ReturnType!(fn_t) RetType; 60 61 int ARGS = 0; 62 // This can make it more convenient to call this with 0 args. 63 if (args !is null) { 64 ARGS = PyObject_Length(args); 65 assert(ARGS == MAX_ARGS, "Function called with wrong number of arguments"); 66 } 67 68 // Sanity check! 69 if (ARGS != MAX_ARGS) { 70 PyErr_SetString(PyExc_TypeError, 71 "Wrong number of arguments. Got " ~ 72 toString(ARGS) ~ 73 ", expected " ~ 74 toString(MAX_ARGS) ~ 75 " args."); 76 handle_exception(); 77 } 78 79 // I've refactored this to use a tuple rather than the old cascade of 80 // variable function calls. There are now 10 calls to d_type where there 81 // once were 110. 82 alias tuple_from_fn!(fn_t) t_t; // tuple type 83 t_t t; 84 85 static if (MAX_ARGS >= 1) 86 t.set!(0)(d_type!(t_t.TypeNo!(0))(PyTuple_GetItem(args, 0))); 87 static if (MAX_ARGS >= 2) 88 t.set!(1)(d_type!(t_t.TypeNo!(1))(PyTuple_GetItem(args, 1))); 89 static if (MAX_ARGS >= 3) 90 t.set!(2)(d_type!(t_t.TypeNo!(2))(PyTuple_GetItem(args, 2))); 91 static if (MAX_ARGS >= 4) 92 t.set!(3)(d_type!(t_t.TypeNo!(3))(PyTuple_GetItem(args, 3))); 93 static if (MAX_ARGS >= 5) 94 t.set!(4)(d_type!(t_t.TypeNo!(4))(PyTuple_GetItem(args, 4))); 95 static if (MAX_ARGS >= 6) 96 t.set!(5)(d_type!(t_t.TypeNo!(5))(PyTuple_GetItem(args, 5))); 97 static if (MAX_ARGS >= 7) 98 t.set!(6)(d_type!(t_t.TypeNo!(6))(PyTuple_GetItem(args, 6))); 99 static if (MAX_ARGS >= 8) 100 t.set!(7)(d_type!(t_t.TypeNo!(7))(PyTuple_GetItem(args, 7))); 101 static if (MAX_ARGS >= 9) 102 t.set!(8)(d_type!(t_t.TypeNo!(8))(PyTuple_GetItem(args, 8))); 103 static if (MAX_ARGS >= 10) 104 t.set!(9)(d_type!(t_t.TypeNo!(9))(PyTuple_GetItem(args, 9))); 105 106 static if (is(RetType : void)) { 107 apply_tuple_to_fn(t, fn); 108 return; 109 } else { 110 return apply_tuple_to_fn(t, fn); 111 } 112 } 113 114 template wrapped_func_call(fn_t/*, uint MIN_ARGS*/) { 56 115 const uint MAX_ARGS = NumberOfArgs!(fn_t); 57 116 alias ReturnType!(fn_t) RetType; … … 62 121 return null; 63 122 } 64 fn_t real_fn = (cast(wrapped_class_object!(fn_t)*)self).d_obj; 123 124 fn_t fn = (cast(wrapped_class_object!(fn_t)*)self).d_obj; 65 125 PyObject* ret; 66 126 67 // If C is specified, then this is a method call. We need to pull out 68 // the "self" object that is the first item in args and turn the member 69 // function pointer in real_fn into a delegate. This conversion is done 70 // with a dirty hack; see dg_convert.d. 71 static if (!is(C == void)) { 72 C instance = (cast(wrapped_class_object!(C)*)PyTuple_GetItem(args, 0)).d_obj; 73 fn_to_dg!(fn_t) fn = dg_wrapper!(C, fn_t)(instance, real_fn); 74 // Pull out the first argument. 75 args = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); 76 scope(exit) Py_DECREF(args); 77 // If C is not specified, then this is just a normal function call. 78 } else { 79 fn_t fn = real_fn; 80 } 81 82 // Sanity check! 83 int ARGS = 0; 84 // This can make it more convenient to call this with 0 args. 85 if (args !is null) 86 ARGS = PyObject_Length(args); 87 if (ARGS < MIN_ARGS || ARGS > MAX_ARGS) { 88 PyErr_SetString(PyExc_TypeError, 89 "Wrong number of arguments. Got " ~ 90 toString(ARGS) ~ 91 ", expected between " ~ 92 toString(MIN_ARGS) ~ "-" ~ toString(MAX_ARGS) ~ 93 " args."); 94 return null; 95 } 96 97 try { /* begin try */ 98 99 static if (MIN_ARGS <= 0 && MAX_ARGS >= 0) { 100 if (ARGS == 0) { 101 // If the return type is void... 102 static if (is(RetType : void)) { 103 fn(); 104 // Return Py_None 105 Py_INCREF(Py_None); 106 ret = Py_None; 107 } else { 108 // Otherwise, return a conversion of the return value 109 ret = _py( fn() ); 110 } 127 try { 128 static if (is(RetType == void)) { 129 py_call/+!(fn_t/*, MIN_ARGS*/)+/(fn, args); 130 Py_INCREF(Py_None); 131 ret = Py_None; 132 } else { 133 ret = _py( py_call/+!(fn_t/*, MIN_ARGS*/)+/(fn, args) ); 111 134 } 112 } static if (MIN_ARGS <= 1 && MAX_ARGS >= 1) { 113 if (ARGS == 1) { 114 // See, this ugly code works like this: 115 // (1) _py takes the return type of the wrapped function, and 116 // converts it to a PyObject*, which is passed straight back into 117 // Python. 118 // (2) fn is the wrapped function. Each of its arguments take the 119 // form: 120 // (3) d_type is a template function. It converts a PyObject* into 121 // a reasonable D type. The template argument is the type to 122 // convert to. The function argument is the PyObject* to convert. 123 // (4) ArgType derives the type of an argument to the function. It 124 // (therefore) is used to pass the correct type into d_type's 125 // template argument. 126 // This pattern is repeated umpteen times, as each number of 127 // function arguments requires its own statement TWICE, as void 128 // return types must be handled differently. 129 static if (is(RetType : void)) { 130 // Call with void return type 131 fn( 132 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)) 133 ); 134 // Return Py_None 135 Py_INCREF(Py_None); 136 ret = Py_None; 137 } else { 138 // Capture return value 139 ret = _py( fn( 140 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)) 141 ) ); 142 } 143 } 144 } static if (MIN_ARGS <= 2 && MAX_ARGS >= 2) { 145 if (ARGS == 2) { 146 static if (is(RetType : void)) { 147 fn( 148 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 149 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)) 150 ); 151 Py_INCREF(Py_None); 152 ret = Py_None; 153 } else { 154 ret = _py( fn( 155 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 156 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)) 157 ) ); 158 } 159 } 160 } static if (MIN_ARGS <= 3 && MAX_ARGS >= 3) { 161 if (ARGS == 3) { 162 static if (is(RetType : void)) { 163 fn( 164 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 165 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 166 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)) 167 ); 168 Py_INCREF(Py_None); 169 ret = Py_None; 170 } else { 171 ret = _py( fn( 172 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 173 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 174 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)) 175 ) ); 176 } 177 } 178 } static if (MIN_ARGS <= 4 && MAX_ARGS >= 4) { 179 if (ARGS == 4) { 180 static if (is(RetType : void)) { 181 fn( 182 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 183 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 184 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 185 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)) 186 ); 187 Py_INCREF(Py_None); 188 ret = Py_None; 189 } else { 190 ret = _py( fn( 191 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 192 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 193 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 194 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)) 195 ) ); 196 } 197 } 198 } static if (MIN_ARGS <= 5 && MAX_ARGS >= 5) { 199 if (ARGS == 5) { 200 static if (is(RetType : void)) { 201 fn( 202 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 203 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 204 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 205 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 206 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)) 207 ); 208 Py_INCREF(Py_None); 209 ret = Py_None; 210 } else { 211 ret = _py( fn( 212 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 213 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 214 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 215 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 216 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)) 217 ) ); 218 } 219 } 220 } static if (MIN_ARGS <= 6 && MAX_ARGS >= 6) { 221 if (ARGS == 6) { 222 static if (is(RetType : void)) { 223 fn( 224 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 225 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 226 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 227 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 228 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)), 229 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)) 230 ); 231 Py_INCREF(Py_None); 232 ret = Py_None; 233 } else { 234 ret = _py( fn( 235 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 236 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 237 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 238 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 239 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)), 240 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)) 241 ) ); 242 } 243 } 244 } static if (MIN_ARGS <= 7 && MAX_ARGS >= 7) { 245 if (ARGS == 7) { 246 static if (is(RetType : void)) { 247 fn( 248 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 249 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 250 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 251 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 252 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)), 253 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)), 254 d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6)) 255 ); 256 Py_INCREF(Py_None); 257 ret = Py_None; 258 } else { 259 ret = _py( fn( 260 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 261 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 262 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 263 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 264 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)), 265 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)), 266 d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6)) 267 ) ); 268 } 269 } 270 } static if (MIN_ARGS <= 8 && MAX_ARGS >= 8) { 271 if (ARGS == 8) { 272 static if (is(RetType : void)) { 273 fn( 274 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 275 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 276 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 277 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 278 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)), 279 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)), 280 d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6)), 281 d_type!(ArgType!(fn_t, 8))(PyTuple_GetItem(args, 7)) 282 ); 283
