Changeset 26
- Timestamp:
- 07/05/06 17:09:25 (2 years ago)
- Files:
-
- trunk/build_manifest.py (modified) (1 diff)
- trunk/build_manifest.pyc (deleted)
- trunk/dcompiler.py (modified) (1 diff)
- trunk/examples/testdll/testdll.d (modified) (3 diffs)
- trunk/infrastructure/pyd/class_wrap.d (modified) (12 diffs)
- trunk/infrastructure/pyd/def.d (modified) (3 diffs)
- trunk/infrastructure/pyd/ftype.d (modified) (5 diffs)
- trunk/infrastructure/pyd/func_wrap.d (added)
- trunk/infrastructure/pyd/generators/ftype.py (added)
- trunk/infrastructure/pyd/generators/min_args.py (added)
- trunk/infrastructure/pyd/generators/min_args.txt (added)
- trunk/infrastructure/pyd/generators/op_wrap.py (added)
- trunk/infrastructure/pyd/generators/op_wrap.txt (added)
- trunk/infrastructure/pyd/make_object.d (modified) (2 diffs)
- trunk/infrastructure/pyd/op_wrap.d (added)
- trunk/infrastructure/pyd/pyd.d (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/build_manifest.py
r24 r26 6 6 '.marks', # jEdit bookmark files 7 7 '.map', # Created automatically by the DMD compiler; needn't distribute. 8 '.swp', # Vim swap files 8 9 ] 9 10 trunk/dcompiler.py
r24 r26 31 31 'exception.d', 32 32 'ftype.d', 33 'func_wrap.d', 33 34 'make_object.d', 34 35 'object.d', 36 'op_wrap.d', 35 37 'pyd.d', 36 38 ] trunk/examples/testdll/testdll.d
r24 r26 43 43 writefln("Foo.foo(): i = %s", m_i); 44 44 } 45 Foo opAdd(Foo f) { return new Foo(m_i + f.m_i); } 45 46 int i() { return m_i; } 46 47 void i(int j) { m_i = j; } 48 } 49 50 void iter_test(PyObject* c) { 51 Bar b = new Bar(1, 2, 3, 4, 5); 52 PyObject* o, res; 53 foreach(i; b) { 54 o = _py(i); 55 res = PyObject_CallFunctionObjArgs(c, o, null); 56 Py_DECREF(res); 57 Py_DECREF(o); 58 } 59 } 60 61 void delegate() func_test() { 62 Foo f = new Foo(20); 63 return &f.foo; 64 } 65 66 class Bar { 67 int[] m_a; 68 this() { } 69 this(int[] i ...) { m_a = i; } 70 int opApply(int delegate(inout int) dg) { 71 int result = 0; 72 for (int i=0; i<m_a.length; ++i) { 73 result = dg(m_a[i]); 74 if (result) break; 75 } 76 return result; 77 } 47 78 } 48 79 … … 55 86 extern (C) 56 87 export void inittestdll() { 88 module_init("testdll"); 89 57 90 def!("foo", foo); 58 91 // Python does not support function overloading. This allows us to wrap … … 60 93 def!("foo2", foo, 1, void function(int)); 61 94 def!("bar", bar); 62 // Minimum argument count.63 def!("baz", baz , 0);95 // Default argument support - Now implicit! 96 def!("baz", baz); 64 97 def!("spam", spam); 65 66 module_init("testdll");98 def!("iter_test", iter_test); 99 def!("func_test", func_test); 67 100 68 101 wrapped_class!("Foo", Foo) f; trunk/infrastructure/pyd/class_wrap.d
r25 r26 23 23 24 24 private import python; 25 25 26 private import pyd.ctor_wrap; 26 27 private import pyd.def; 27 28 private import pyd.ftype; 29 private import pyd.func_wrap; 28 30 private import pyd.make_object; 31 private import pyd.op_wrap; 32 29 33 private import std.string; 34 35 template DPyObject_HEAD(T) { 36 mixin PyObject_HEAD; 37 T d_obj; 38 } 30 39 31 40 /// The class object, a subtype of PyObject … … 33 42 extern(C) 34 43 struct wrapped_class_object { 35 mixin PyObject_HEAD; 36 T d_obj; 44 mixin DPyObject_HEAD!(T); 37 45 } 38 46 } … … 46 54 0, /*ob_size*/ 47 55 null, /*tp_name*/ 48 (wrapped_class_object!(T)).sizeof,/*tp_basicsize*/56 0, /*tp_basicsize*/ 49 57 0, /*tp_itemsize*/ 50 58 &wrapped_methods!(T).wrapped_dealloc, /*tp_dealloc*/ … … 53 61 null, /*tp_setattr*/ 54 62 null, /*tp_compare*/ 55 &wrapped_methods!(T).wrapped_repr,/*tp_repr*/63 null, /*tp_repr*/ 56 64 null, /*tp_as_number*/ 57 65 null, /*tp_as_sequence*/ … … 63 71 null, /*tp_setattro*/ 64 72 null, /*tp_as_buffer*/ 65 Py_TPFLAGS_DEFAULT ,/*tp_flags*/73 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 66 74 null, /*tp_doc*/ 67 75 null, /* tp_traverse */ … … 114 122 wrap_object* self = cast(wrap_object*)_self; 115 123 if (self.d_obj !is null) { 116 wrap_class_instances!(T)[self.d_obj] = wrap_class_instances!(T)[self.d_obj] - 1;117 if (wrap_class_instances!(T)[self.d_obj] == 0) {124 wrap_class_instances!(T)[self.d_obj]--; 125 if (wrap_class_instances!(T)[self.d_obj] <= 0) { 118 126 wrap_class_instances!(T).remove(self.d_obj); 119 127 } … … 121 129 self.ob_type.tp_free(self); 122 130 } 123 131 } 132 133 template wrapped_repr(T) { 134 alias wrapped_class_object!(T) wrap_object; 124 135 /// The default repr method calls the class's toString. 125 136 extern(C) 126 PyObject* wrapped_repr(PyObject* _self) {137 PyObject* repr(PyObject* _self) { 127 138 wrap_object* self = cast(wrap_object*)_self; 128 139 char[] repr = self.d_obj.toString(); … … 137 148 extern(C) 138 149 int init(PyObject* self, PyObject* args, PyObject* kwds) { 139 // TODO: Provide better constructor support...140 150 T t = new T; 141 151 (cast(wrap_object*)self).d_obj = t; … … 190 200 191 201 // The set of all instances of this class that are passed into Python. Keeping 192 // references here in D is needed to keep the GC happy. 193 // XXX: This currently fails if the same reference is held by multiple Python 194 // objects. 202 // references here in D is needed to keep the GC happy. The integer value is 203 // used to make this a sort of poor man's multiset. 195 204 template wrap_class_instances(T) { 196 205 int[T] wrap_class_instances; … … 237 246 * if more than one function has the same name as this one. 238 247 */ 239 template def(char[] name, alias fn, uint MIN_ARGS = NumberOfArgs!(typeof(&fn)), fn_t=typeof(&fn)) {248 template def(char[] name, alias fn, uint MIN_ARGS = MIN_ARGS!(fn), fn_t=typeof(&fn)) { 240 249 static void def() { 241 250 static PyMethodDef empty = { null, null, 0, null }; 242 wrapped_method_list!(T)[length-1].ml_name = name ~ \0;243 wrapped_method_list!(T)[length-1].ml_meth =244 cast(PyCFunction)&func_wrap!(fn, MIN_ARGS, T, fn_t).func;245 wrapped_method_list!(T)[length-1].ml_flags = METH_VARARGS;246 wrapped_method_list!(T)[length-1].ml_doc = "";247 wrapped_method_list!(T)~= empty;251 alias wrapped_method_list!(T) list; 252 list[length-1].ml_name = name ~ \0; 253 list[length-1].ml_meth = &func_wrap!(fn, MIN_ARGS, T, fn_t).func; 254 list[length-1].ml_flags = METH_VARARGS; 255 list[length-1].ml_doc = ""; 256 list ~= empty; 248 257 // It's possible that appending the empty item invalidated the 249 258 // pointer in the type struct, so we renew it here. 250 wrapped_class_type!(T).tp_methods = 251 wrapped_method_list!(T); 259 wrapped_class_type!(T).tp_methods = list; 252 260 } 253 261 } … … 308 316 void finalize_class(CLS) (CLS cls) { 309 317 alias typeof(cls.t) T; 318 alias wrapped_class_type!(T) type; 310 319 const char[] name = CLS._name; 311 320 … … 313 322 char[] module_name = .toString(PyModule_GetName(DPy_Module_p)); 314 323 315 wrapped_class_type!(T).ob_type = PyType_Type_p; 316 wrapped_class_type!(T).tp_doc = name ~ " objects" ~ \0; 317 wrapped_class_type!(T).tp_new = &PyType_GenericNew; 318 wrapped_class_type!(T).tp_methods = wrapped_method_list!(T); 319 wrapped_class_type!(T).tp_name = 320 module_name ~ "." ~ name ~ \0; 324 // Fill in missing values 325 type.ob_type = PyType_Type_p; 326 type.tp_basicsize = (wrapped_class_object!(T)).sizeof; 327 type.tp_doc = name ~ " objects" ~ \0; 328 //type.tp_new = &PyType_GenericNew; 329 type.tp_repr = &wrapped_repr!(T).repr; 330 type.tp_methods = wrapped_method_list!(T); 331 type.tp_name = module_name ~ "." ~ name ~ \0; 332 if (wrapped_class_as_number!(T) != PyNumberMethods.init) { 333 type.tp_as_number = &wrapped_class_as_number!(T); 334 } 321 335 322 336 // If a ctor wasn't supplied, try the default. 323 if (wrapped_class_type!(T).tp_init is null) { 324 wrapped_class_type!(T).tp_init = 325 &wrapped_init!(T).init; 326 } 327 if (PyType_Ready(&wrapped_class_type!(T)) < 0) { 337 if (type.tp_init is null) { 338 type.tp_init = &wrapped_init!(T).init; 339 } 340 if (PyType_Ready(&type) < 0) { 328 341 // XXX: This will probably crash the interpreter, as it isn't normally 329 342 // caught and translated. 330 343 throw new Exception("Couldn't ready wrapped type!"); 331 344 } 332 Py_INCREF(cast(PyObject*)& wrapped_class_type!(T));333 PyModule_AddObject(DPy_Module_p, name, cast(PyObject*)& wrapped_class_type!(T));345 Py_INCREF(cast(PyObject*)&type); 346 PyModule_AddObject(DPy_Module_p, name, cast(PyObject*)&type); 334 347 is_wrapped!(T) = true; 335 348 } trunk/infrastructure/pyd/def.d
r25 r26 23 23 24 24 private import python; 25 26 private import pyd.class_wrap; 27 private import pyd.dg_convert; 28 private import pyd.exception; 29 private import pyd.ftype; 30 private import pyd.func_wrap; 25 31 private import pyd.make_object; 26 private import pyd.object; 27 private import pyd.ftype; 28 private import pyd.exception; 29 private import pyd.dg_convert; 30 private import pyd.class_wrap; 32 31 33 private import std.string; 32 34 … … 75 77 *It's greater than 10!) 76 78 */ 77 template def(char[] name, alias fn, uint MIN_ARGS = NumberOfArgs!(typeof(&fn)), fn_t=typeof(&fn)) {79 template def(char[] name, alias fn, uint MIN_ARGS = MIN_ARGS!(fn), fn_t=typeof(&fn)) { 78 80 void def() { 79 static PyMethodDef empty = { null, null, 0, null }; 80 module_global_methods[length-1].ml_name = name ~ \0; 81 module_global_methods[length-1].ml_meth = 82 cast(PyCFunction)&func_wrap!(fn, MIN_ARGS, void, fn_t).func; 83 module_global_methods[length-1].ml_flags = METH_VARARGS; 84 module_global_methods[length-1].ml_doc = ""; 85 module_global_methods ~= empty; 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); 86 85 } 87 86 } … … 96 95 } 97 96 98 template func_wrap(alias real_fn, uint MIN_ARGS, C=void, fn_t=typeof(&real_fn)) {99 //typeof(&r_fn) fn = &r_fn;100 //alias typeof(&real_fn) fn_t;101 const uint MAX_ARGS = NumberOfArgs!(fn_t);102 alias ReturnType!(fn_t) RetType;103 extern (C)104 PyObject* func(PyObject* self, PyObject* args) {105 PyObject* ret;106 107 // If C is specified, then this is a method call. We need to pull out108 // the object in self and turn the member function pointer in real_fn109 // into a delegate. This conversion is done with a dirty hack; see110 // dg_convert.d.111 static if (!is(C == void)) {112 // Didn't pass a "self" parameter! Ack!113 if (self is null) {114 PyErr_SetString(PyExc_TypeError, "Wrapped method didn't get a 'self' parameter.");115 return null;116 }117 C instance = (cast(wrapped_class_object!(C)*)self).d_obj;118 fn_to_dg!(fn_t) fn = dg_wrapper!(C, fn_t)(instance, &real_fn);119 // If C is not specified, then this is just a normal function call.120 } else {121 fn_t fn = &real_fn;122 }123 124 // Sanity check!125 int ARGS = 0;126 // This can make it more convenient to call this with 0 args.127 if (args !is null)128 ARGS = PyObject_Length(args);129 if (ARGS < MIN_ARGS || ARGS > MAX_ARGS) {130 PyErr_SetString(PyExc_TypeError, "Wrong number of arguments. Got " ~ toString(ARGS) ~ ", expected between " ~ toString(MIN_ARGS) ~ "-" ~ toString(MAX_ARGS) ~ " args.");131 return null;132 }133 134 try { /* begin try */135 136 static if (MIN_ARGS <= 0 && MAX_ARGS >= 0) {137 if (ARGS == 0) {138 // If the return type is void...139 static if (is(RetType : void)) {140 fn();141 // Return Py_None142 Py_INCREF(Py_None);143 ret = Py_None;144 } else {145 // Otherwise, return a conversion of the return value146 ret = _py( fn() );147 }148 }149 } static if (MIN_ARGS <= 1 && MAX_ARGS >= 1) {150 if (ARGS == 1) {151 // See, this ugly code works like this:152 // (1) _py takes the return type of the wrapped function, and153 // converts it to a PyObject*, which is passed straight back into154 // Python.155 // (2) fn is the wrapped function. Each of its arguments take the156 // form:157 // (3) d_type is a template function. It converts a PyObject* into158 // a reasonable D type. The template argument is the type to159 // convert to. The function argument is the PyObject* to convert.160 // (4) ArgType derives the type of an argument to the function. It161 // (therefore) is used to pass the correct type into d_type's162 // template argument.163 // This pattern is repeated umpteen times, as each number of164 // function arguments requires its own statement TWICE, as void165 // return types must be handled differently.166 static if (is(RetType : void)) {167 // Call with void return type168 fn(169 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0))170 );171 // Return Py_None172 Py_INCREF(Py_None);173 ret = Py_None;174 } else {175 // Capture return value176 ret = _py( fn(177 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0))178 ) );179 }180 }181 } static if (MIN_ARGS <= 2 && MAX_ARGS >= 2) {182 if (ARGS == 2) {183 static if (is(RetType : void)) {184 fn(185 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),186 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1))187 );188 Py_INCREF(Py_None);189 ret = Py_None;190 } else {191 ret = _py( fn(192 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),193 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1))194 ) );195 }196 }197 } static if (MIN_ARGS <= 3 && MAX_ARGS >= 3) {198 if (ARGS == 3) {199 static if (is(RetType : void)) {200 fn(201 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),202 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),203 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2))204 );205 Py_INCREF(Py_None);206 ret = Py_None;207 } else {208 ret = _py( fn(209 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),210 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),211 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2))212 ) );213 }214 }215 } static if (MIN_ARGS <= 4 && MAX_ARGS >= 4) {216 if (ARGS == 4) {217 static if (is(RetType : void)) {218 fn(219 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),220 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),221 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),222 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3))223 );224 Py_INCREF(Py_None);225 ret = Py_None;226 } else {227 ret = _py( fn(228 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),229 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),230 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),231 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3))232 ) );233 }234 }235 } static if (MIN_ARGS <= 5 && MAX_ARGS >= 5) {236 if (ARGS == 5) {237 static if (is(RetType : void)) {238 fn(239 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),240 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),241 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),242 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)),243 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4))244 );245 Py_INCREF(Py_None);246 ret = Py_None;247 } else {248 ret = _py( fn(249 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),250 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),251 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),252 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)),253 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4))254 ) );255 }256 }257 } static if (MIN_ARGS <= 6 && MAX_ARGS >= 6) {258 if (ARGS == 6) {259 static if (is(RetType : void)) {260 fn(261 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),262 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),263 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),264 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)),265 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)),266 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5))267 );268 Py_INCREF(Py_None);269 ret = Py_None;270 } else {271 ret = _py( fn(272 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),273 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),274 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),275 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)),276 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)),277 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5))278 ) );279 }280 }281 } static if (MIN_ARGS <= 7 && MAX_ARGS >= 7) {282 if (ARGS == 7) {283 static if (is(RetType : void)) {284 fn(285 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),286 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),287 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),288 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)),289 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)),290 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)),291 d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6))292 );293 Py_INCREF(Py_None);294 ret = Py_None;295 } else {296 ret = _py( fn(297 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),298 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),299 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),300 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)),301 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)),302 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)),303 d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6))304 ) );305 }306 }307 } static if (MIN_ARGS <= 8 && MAX_ARGS >= 8) {308 if (ARGS == 8) {309 static if (is(RetType : void)) {310 fn(311 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),312 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),313 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),314 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)),315 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)),316 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)),317 d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6)),318 d_type!(ArgType!(fn_t, 8))(PyTuple_GetItem(args, 7))319 );320 Py_INCREF(Py_None);321 ret = Py_None;322 } else {323 ret = _py( fn(324 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),325 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),326 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),327 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)),328 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)),329 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)),330 d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6)),331 d_type!(ArgType!(fn_t, 8))(PyTuple_GetItem(args, 7))332 ) );333 }334 }335 } static if (MIN_ARGS <= 9 && MAX_ARGS >= 9) {336 if (ARGS == 9) {337 static if (is(RetType : void)) {338 fn(339 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),340 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),341 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),342 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)),343 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)),344 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)),345 d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6)),346 d_type!(ArgType!(fn_t, 8))(PyTuple_GetItem(args, 7)),347 d_type!(ArgType!(fn_t, 9))(PyTuple_GetItem(args, 8))348 );349 Py_INCREF(Py_None);350 ret = Py_None;351 } else {352 ret = _py( fn(353 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),354 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),355 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),356 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)),357 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)),358 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)),359 d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6)),360 d_type!(ArgType!(fn_t, 8))(PyTuple_GetItem(args, 7)),361 d_type!(ArgType!(fn_t, 9))(PyTuple_GetItem(args, 8))362 ) );363 }364 }365 } static if (MIN_ARGS <= 10 && MAX_ARGS >= 10) {366 if (ARGS == 10) {367 static if (is(RetType : void)) {368 fn(369 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),370 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),371 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),372 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)),373 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)),374 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)),375 d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6)),376 d_type!(ArgType!(fn_t, 8))(PyTuple_GetItem(args, 7)),377 d_type!(ArgType!(fn_t, 9))(PyTuple_GetItem(args, 8)),378 d_type!(ArgType!(fn_t, 10))(PyTuple_GetItem(args, 9))379 );380 Py_INCREF(Py_None);381 ret = Py_None;382 } else {383 ret = _py( fn(384 d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)),385 d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)),386 d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)),387 d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)),388 d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)),389 d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)),390 d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6)),391 d_type!(ArgType!(fn_t, 8))(PyTuple_GetItem(args, 7)),392 d_type!(ArgType!(fn_t, 9))(PyTuple_GetItem(args, 8)),393 d_type!(ArgType!(fn_t, 10))(PyTuple_GetItem(args, 9))394 ) );395 }396 }397 }398 399 } /* end try */400 // A Python exception was raised and duly re-thrown as a D exception.401 // It should now be re-raised as a Python exception.402 catch (PythonException e) {403 PyErr_Restore(e.type(), e.value(), e.traceback());404 return null;405 }406 // A D exception was raised and should be translated into a meaningful407 // Python exception.408 catch (Exception e) {409 PyErr_SetString(PyExc_RuntimeError, "D Exception: " ~ e.classinfo.name ~ ": " ~ e.msg ~ \0);410 return null;411 }412 return ret;413 }414 }415 trunk/infrastructure/pyd/ftype.d
r24 r26 1 /*2 Copyright (c) 2006 Daniel Keep, Tomasz Stachowiak3 4 Permission is hereby granted, free of charge, to any person obtaining a copy of5 this software and associated documentation files (the "Software"), to deal in6 the Software without restriction, including without limitation the rights to7 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies8 of the Software, and to permit persons to whom the Software is furnished to do9 so, subject to the following conditions:10 11 The above copyright notice and this permission notice shall be included in all12 copies or substantial portions of the Software.13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE20 SOFTWARE.21 */22 23 1 /** 24 * This module contains template sfor inferring the number of arguments,2 * This module contains template for inferring the number of arguments, 25 3 * the return type, and argument types of an arbitrary function pointer. 26 4 * 27 * Portions of this module were automatically generated by Python modules. 28 * 29 * Authors: Daniel Keep, Tomasz Stachowiak 30 * Date: $(DATETIME) 5 * This module was automatically generated by ftype.py 6 * 7 * Written by Daniel Keep. 8 * Released to public domainâshare and enjoy (just leave my name in it, 9 * pretty please). 31 10 */ 32 11 module pyd.ftype; … … 137 116 } 138 117 118 template 119 NumberOfArgsSwitchT(Tf) 120 { 121 static if( is( typeof(*Tf) == function ) ) 122 alias NumberOfArgsT!(Tf).type type; 123 else static if( is( Tf U == delegate ) ) 124 alias NumberOfArgsSwitchT!(U*).type type; 125 else static if( (is( T == class ) || is( T == struct )) && is(typeof(&T.opCall)) ) 126 alias NumberOfArgsSwitchT!(typeof(&T.opCall)).type type; 127 } 128 139 129 /** 140 * Derives the number of arguments the passed function type accepts. It only 141 * works on functions with 10 or fewer arguments. 130 * This template will attempt to determine the number of arguments the 131 * supplied function pointer or delegate type takes. It supports a maximum of 132 * 10 arguments. 133 * 134 * Example: 135 * ---------------------------------------- 136 * void fnWithThreeArgs(byte a, short b, int c) {} 137 * const uint numArgs = NumberOfArgs!(typeof(&fnWithThreeArgs)); 138 * ---------------------------------------- 142 139 */ 143 140 public … … 145 142 NumberOfArgs(Tf) 146 143 { 147 const uint NumberOfArgs = ArglenConvT!(NumberOfArgsT!(Tf).type); 148 } 149 150 // Thanks to Tomasz Stachowiak for the Deref and ReturnType templates! 151 template Deref(T) { 152 alias typeof(*T) Deref; 144 const uint NumberOfArgs = ArglenConvT!(NumberOfArgsSwitchT!(Tf).type); 145 } 146 147 template 148 ReturnTypeT(Tf) 149 { 150 private Tf fptr; 151 static if( is( typeof(*Tf) U == function ) ) 152 alias U type; 153 else static if( is( Tf U == delegate ) ) 154 alias ReturnType!(U*) type; 155 else static if( (is( T == class ) || is( T == struct )) && is(typeof(&T.opCall)) ) 156 alias ReturnTypeT!(typeof(&T.opCall)).type type; 157 else 158 static assert(false, "ReturnType argument must be function pointer" 159 " or delegate."); 153 160 } 154 161 155 162 /** 156 * Derives the return type of the passed function type. 163 * This template will attempt to discern the return type of the supplied 164 * function pointer or delegate type. It supports callables with a maximum of 165 * 10 arguments. 166 * 167 * Example: 168 * ---------------------------------------- 169 * uint returnsANumber() { return 42; } 170 * alias ReturnType!(typeof(&returnsANumber)) RType; // RType == uint 171 * ---------------------------------------- 157 172 */ 158 173 public 159 template ReturnType(T) { 160 static if (is(Deref!(T) U == function)) { 161 alias U ReturnType; 162 } else static if (is(Deref!(T) U == delegate)) { 163 alias ReturnType!(U) ReturnType; 164 } else static assert (false); 174 template 175 ReturnType(Tf) 176 { 177 alias ReturnTypeT!(Tf).type ReturnType; 165 178 } 166 179 … … 502 515 private Tf fptr; 503 516 static if( n == 1 ) 504 alias typeof(Arg1TypeT( Tf)) type;517 alias typeof(Arg1TypeT(fptr)) type; 505 518 else static if( n == 2 ) 506 alias typeof(Arg2TypeT( Tf)) type;519 alias typeof(Arg2TypeT(fptr)) type; 507 520 else static if( n == 3 ) 508 alias typeof(Arg3TypeT( Tf)) type;521 alias typeof(Arg3TypeT(fptr)) type; 509 522 else static if( n == 4 ) 510 alias typeof(Arg4TypeT( Tf)) type;523 alias typeof(Arg4TypeT(fptr)) type; 511 524 else static if( n == 5 ) 512 alias typeof(Arg5TypeT( Tf)) type;525 alias typeof(Arg5TypeT(fptr)) type; 513 526 else static if( n == 6 ) 514 alias typeof(Arg6TypeT( Tf)) type;527 alias typeof(Arg6TypeT(fptr)) type; 515 528 else static if( n == 7 ) 516 alias typeof(Arg7TypeT( Tf)) type;529 alias typeof(Arg7TypeT(fptr)) type; 517 530 else static if( n == 8 ) 518 alias typeof(Arg8TypeT( Tf)) type;531 alias typeof(Arg8TypeT(fptr)) type; 519 532 else static if( n == 9 ) 520 alias typeof(Arg9TypeT( Tf)) type;533 alias typeof(Arg9TypeT(fptr)) type; 521 534 else static if( n == 10 ) 522 alias typeof(Arg10TypeT( Tf)) type;535 alias typeof(Arg10TypeT(fptr)) type; 523 536 else 524 { static assert(false); } 537 static assert(false, 538 "Maximum of 10 arguments supported."); 539 } 540 541 template 542 ArgTypeSwitchT(Tf, uint n) 543 { 544 static if( is( typeof(*Tf) == function ) ) 545 alias ArgTypeT!(Tf, n).type type; 546 else static if( is( Tf U == delegate ) ) 547 alias ArgTypeSwitchT!(U*, n).type type; 548 else static if( (is( T == class ) || is( T == struct )) && is(typeof(&T.opCall)) ) 549 alias ArgTypeSwitchT!(typeof(&T.opCall)).type type; 550 else 551 static assert(false, "ArgType argument must be a function pointer" 552 " or a delegate."); 525 553 } 526 554 527 555 /** 528 * Derives the type of an individual argument of function Tf. 529 * Params: 530 * Tf = A function pointer type 531 * n = The 1-indexed function argument to get the type of, e.g.: 532 * $(D_CODE int func(int, char, real); 533 *static assert( is(char == _ArgType(&func, 2)) );) 556 * This template will attempt to extract the type of the nth argument of the 557 * given function pointer or delegate type. It supports callables with up to 558 * 10 arguments. 559 * 560 * Example: 561 * ---------------------------------------- 562 * void intShortBool(int a, short b, bool c) {} 563 * alias ArgType!(typeof(&intShortBool), 2) TArg2; // TArg2 == short 564 * ---------------------------------------- 534 565 */ 535 566 public … … 537 568 ArgType(Tf, uint n) 538 569 { 539 alias ArgTypeT!(Tf, n).type ArgType; 540 } 541 570 alias ArgTypeSwitchT!(Tf, n).type ArgType; 571 } 572 573 template MIN_ARGS_T(alias fn) { 574 alias typeof(&fn) fn_t; 575 static if (is(typeof(fn()))) 576 const uint MIN_ARGS = 0; 577 else static if (is(typeof(fn(ArgType!(fn_t, 1).init)))) 578 const uint MIN_ARGS = 1; 579 else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init)))) 580 const uint MIN_ARGS = 2; 581 else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init)))) 582 const uint MIN_ARGS = 3; 583 else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init)))) 584 const uint MIN_ARGS = 4; 585 else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init, ArgType!(fn_t, 5).init)))) 586 const uint MIN_ARGS = 5; 587 else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init, ArgType!(fn_t, 5).init, ArgType!(fn_t, 6).init)))) 588 const uint MIN_ARGS = 6; 589 else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init, ArgType!(fn_t, 5).init, ArgType!(fn_t, 6).init, ArgType!(fn_t, 7).init)))) 590 const uint MIN_ARGS = 7; 591 else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init, ArgType!(fn_t, 5).init, ArgType!(fn_t, 6).init, ArgType!(fn_t, 7).init, ArgType!(fn_t, 8).init)))) 592 const uint MIN_ARGS = 8; 593 else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init, ArgType!(fn_t, 5).init, ArgType!(fn_t, 6).init, ArgType!(fn_t, 7).init, ArgType!(fn_t, 8).init, ArgType!(fn_t, 9).init)))) 594 const uint MIN_ARGS = 9; 595 else static if (is(typeof(fn(ArgType!(fn_t, 1).init, ArgType!(fn_t, 2).init, ArgType!(fn_t, 3).init, ArgType!(fn_t, 4).init, ArgType!(fn_t, 5).init, ArgType!(fn_t, 6).init, ArgType!(fn_t, 7).init, ArgType!(fn_t, 8).init, ArgType!(fn_t, 9).init, ArgType!(fn_t, 10).init)))) 596 const uint MIN_ARGS = 10; 597 } 598 599 /** 600 * 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. 604 */ 605 public 606 template MIN_ARGS(alias fn) { 607 alias MIN_ARGS_T!(fn).MIN_ARGS MIN_ARGS; 608 } 609 610 /* *** Unit tests *** */ 611
