Changeset 37
- Timestamp:
- 08/14/06 21:41:17 (2 years ago)
- Files:
-
- trunk/dcompiler.py (modified) (4 diffs)
- trunk/examples/testdll/test.py (modified) (1 diff)
- trunk/examples/testdll/testdll.d (modified) (1 diff)
- trunk/infrastructure/pyd/class_wrap.d (modified) (8 diffs)
- trunk/infrastructure/pyd/ctor_wrap.d (modified) (1 diff)
- trunk/infrastructure/pyd/exception.d (modified) (2 diffs)
- trunk/infrastructure/pyd/func_wrap.d (modified) (5 diffs)
- trunk/infrastructure/pyd/iteration.d (added)
- trunk/infrastructure/pyd/make_object.d (modified) (10 diffs)
- trunk/infrastructure/pyd/op_wrap.d (modified) (1 diff)
- trunk/infrastructure/st (added)
- trunk/infrastructure/st/coroutine.d (added)
- trunk/infrastructure/st/stackcontext.d (added)
- trunk/infrastructure/st/stackthread.d (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/dcompiler.py
r30 r37 34 34 'ftype.d', 35 35 'func_wrap.d', 36 'iteration.d', 36 37 'make_object.d', 37 38 'op_wrap.d', 38 39 'pyd.d', 39 40 'tuples.d', 41 ] 42 43 _stFiles = [ 44 'coroutine.d', 45 'stackcontext.d', 46 'stackthread.d', 40 47 ] 41 48 … … 125 132 binpath = _qp(self._binpath) 126 133 compileOpts = self._compileOpts 127 #outputOpts = self._outputOpts134 outputOpts = self._outputOpts 128 135 129 136 includePathOpts = [] … … 150 157 ) 151 158 sources.append(filePath) 152 # Add the pyd directory to the include path 159 # And StackThreads 160 for file in _stFiles: 161 filePath = os.path.join(_infraDir, 'st', file) 162 if not os.path.isfile(filePath): 163 raise DistutilsPlatformError("Required StackThreads source" 164 "file '%s' is missing." % filePath 165 ) 166 sources.append(filePath) 167 # Add the infraDir to the include path for Pyd and ST 153 168 includePathOpts += self._includeOpts 154 169 includePathOpts[-1] = includePathOpts[-1] % os.path.join(_infraDir) … … 199 214 optimizationOpts = self._defaultOptimizeOpts 200 215 201 #for source in sources: 202 #outOpts = outputOpts[:] 203 #objName = self.object_filenames([os.path.split(source)[1]], 0, output_dir)[0] 204 #outOpts[-1] = outOpts[-1] % _qp(objName) 205 #cmdElements = ( 206 # [binpath] + extra_preargs + compileOpts + 207 # [pythonVersionOpt, self._unicodeOpt] + optimizationOpts + 208 # includePathOpts + outOpts + userVersionAndDebugOpts + 209 # [_qp(source)] + extra_postargs 210 #) 211 # gdc/gcc doesn't support the idea of an output directory, so we 212 # compile from the destination 213 sources = [_qp(os.path.abspath(s)) for s in sources] 214 cwd = os.getcwd() 215 os.chdir(output_dir) 216 cmdElements = ( 217 [binpath] + extra_preargs + compileOpts + 218 [pythonVersionOpt, self._unicodeOpt] + optimizationOpts + 219 includePathOpts + userVersionAndDebugOpts + 220 sources + extra_postargs 221 ) 222 cmdElements = [el for el in cmdElements if el] 223 224 try: 225 self.spawn(cmdElements) 226 except DistutilsExecError, msg: 216 print 'sources: ', [os.path.basename(s) for s in sources] 217 # Compiling one-by-one exhibits a strange bug in the D front-end, while 218 # compiling all at once works. This flags allows me to test each form 219 # easily. Supporting the one-by-one form is synonymous with GDC support. 220 ONE_BY_ONE = False 221 if ONE_BY_ONE: 222 for source in sources: 223 outOpts = outputOpts[:] 224 objName = self.object_filenames([os.path.split(source)[1]], 0, output_dir)[0] 225 outOpts[-1] = outOpts[-1] % _qp(objName) 226 cmdElements = ( 227 [binpath] + extra_preargs + compileOpts + 228 [pythonVersionOpt, self._unicodeOpt] + optimizationOpts + 229 includePathOpts + outOpts + userVersionAndDebugOpts + 230 [_qp(source)] + extra_postargs 231 ) 232 cmdElements = [el for el in cmdElements if el] 233 try: 234 self.spawn(cmdElements) 235 except DistutilsExecError, msg: 236 raise CompileError(msg) 237 else: 238 # gdc/gcc doesn't support the idea of an output directory, so we 239 # compile from the destination 240 sources = [_qp(os.path.abspath(s)) for s in sources] 241 cwd = os.getcwd() 242 os.chdir(output_dir) 243 cmdElements = ( 244 [binpath] + extra_preargs + compileOpts + 245 [pythonVersionOpt, self._unicodeOpt] + optimizationOpts + 246 includePathOpts + userVersionAndDebugOpts + 247 sources + extra_postargs 248 ) 249 cmdElements = [el for el in cmdElements if el] 250 251 try: 252 self.spawn(cmdElements) 253 except DistutilsExecError, msg: 254 #os.chdir(cwd) 255 raise CompileError(msg) 227 256 os.chdir(cwd) 228 raise CompileError(msg)229 os.chdir(cwd)230 257 231 258 return [os.path.join(output_dir, fn) for fn in os.listdir(output_dir) if fn.endswith(self.obj_extension)] trunk/examples/testdll/test.py
r24 r37 31 31 a.foo() 32 32 33 print "Testing opApply wrapping:" 34 for i in a: 35 print i 36 33 37 print 34 38 trunk/examples/testdll/testdll.d
r28 r37 53 53 } 54 54 Foo opAdd(Foo f) { return new Foo(m_i + f.m_i); } 55 int opApply(int delegate(inout int) dg) { 56 int result = 0; 57 for (int i=0; i<10; ++i) { 58 result = dg(i); 59 if (result) break; 60 } 61 return result; 62 } 55 63 int i() { return m_i; } 56 64 void i(int j) { m_i = j; } trunk/infrastructure/pyd/class_wrap.d
r28 r37 26 26 private import pyd.ctor_wrap; 27 27 private import pyd.def; 28 private import pyd.exception; 28 29 private import pyd.ftype; 29 30 private import pyd.func_wrap; 31 private import pyd.iteration; 30 32 private import pyd.make_object; 31 33 private import pyd.op_wrap; … … 111 113 extern(C) 112 114 PyObject* wrapped_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { 113 wrap_object* self; 114 115 self = cast(wrap_object*)type.tp_alloc(type, 0); 116 if (self !is null) { 117 self.d_obj = null; 118 } 119 120 return cast(PyObject*)self; 115 return exception_catcher(delegate PyObject*() { 116 wrap_object* self; 117 118 self = cast(wrap_object*)type.tp_alloc(type, 0); 119 if (self !is null) { 120 self.d_obj = null; 121 } 122 123 return cast(PyObject*)self; 124 }); 121 125 } 122 126 123 127 /// The generic dealloc method. 124 128 extern(C) 125 void wrapped_dealloc(PyObject* _self) { 126 wrap_object* self = cast(wrap_object*)_self; 127 if (self.d_obj !is null) { 128 wrap_class_instances!(T)[self.d_obj]--; 129 if (wrap_class_instances!(T)[self.d_obj] <= 0) { 130 wrap_class_instances!(T).remove(self.d_obj); 131 } 132 } 133 self.ob_type.tp_free(self); 129 void wrapped_dealloc(PyObject* self) { 130 exception_catcher(delegate PyObject*() { 131 WrapPyObject_SetObj(self, null); 132 self.ob_type.tp_free(self); 133 return null; 134 }); 134 135 } 135 136 } … … 140 141 extern(C) 141 142 PyObject* repr(PyObject* _self) { 142 wrap_object* self = cast(wrap_object*)_self; 143 char[] repr = self.d_obj.toString(); 144 return _py(repr); 143 return exception_catcher({ 144 wrap_object* self = cast(wrap_object*)_self; 145 char[] repr = self.d_obj.toString(); 146 return _py(repr); 147 }); 145 148 } 146 149 } … … 152 155 extern(C) 153 156 int init(PyObject* self, PyObject* args, PyObject* kwds) { 154 T t = new T;155 (cast(wrap_object*)self).d_obj = t;156 wrap_class_instances!(T)[t] = 1;157 return 0;157 return exception_catcher({ 158 WrapPyObject_SetObj(self, new T); 159 return 0; 160 }); 158 161 } 159 162 } … … 182 185 extern(C) 183 186 PyObject* func(PyObject* self, void* closure) { 187 // func_wrap already catches exceptions 184 188 return func_wrap!(Fn, 0, T, property_parts!(Fn).getter_type).func(self, null); 185 189 } … … 193 197 PyObject* temp_tuple = PyTuple_New(1); 194 198 if (temp_tuple is null) return -1; 199 scope(exit) Py_DECREF(temp_tuple); 195 200 Py_INCREF(value); 196 201 PyTuple_SetItem(temp_tuple, 0, value); 197 202 PyObject* res = func_wrap!(Fn, 1, T, property_parts!(Fn).setter_type).func(self, temp_tuple); 198 // We'll get something back, and need to DECREF it. 199 Py_DECREF(res); 200 Py_DECREF(temp_tuple); 203 // If we get something back, we need to DECREF it. 204 if (res) Py_DECREF(res); 205 // If we don't, propagate the exception 206 else return -1; 207 // Otherwise, all is well. 201 208 return 0; 202 209 } … … 341 348 type.tp_as_number = &wrapped_class_as_number!(T); 342 349 } 350 351 static if (is(typeof(&T.opApply))) { 352 DPySC_Ready(); 353 type.tp_iter = &wrapped_iter!(T).iter; 354 } 343 355 344 356 // If a ctor wasn't supplied, try the default. … … 356 368 wrapped_classes[typeid(T)] = true; 357 369 } 370 371 /** 372 * Returns a new Python object of a wrapped type. 373 */ 374 PyObject* WrapPyObject_FromObject(T) (T t) { 375 alias wrapped_class_object!(T) wrapped_object; 376 alias wrapped_class_type!(T) type; 377 if (is_wrapped!(T)) { 378 // Allocate the object 379 wrapped_object* obj = 380 cast(wrapped_object*)type.tp_new(&type, null, null); 381 // Set the contained instance 382 WrapPyObject_SetObj(obj, t); 383 return cast(PyObject*)obj; 384 } else { 385 PyErr_SetString(PyExc_RuntimeError, "Type " ~ typeid(T).toString() ~ " is not wrapped by Pyd."); 386 return null; 387 } 388 } 389 390 T WrapPyObject_AsObject(T) (PyObject* _self) { 391 alias wrapped_class_object!(T) wrapped_object; 392 alias wrapped_class_type!(T) type; 393 wrapped_object* self = cast(wrapped_object*)_self; 394 if (!is_wrapped!(T) || self is null || !PyObject_TypeCheck(_self, &type)) { 395 // Throw something 396 } 397 return self.d_obj; 398 } 399 400 /** 401 * Sets the contained object in self to t. 402 */ 403 void WrapPyObject_SetObj(PY, T) (PY* _self, T t) { 404 alias wrapped_class_object!(T) obj; 405 obj* self = cast(obj*)_self; 406 // Clean up the old object, if there is one 407 if (self.d_obj !is null) { 408 wrap_class_instances!(T)[self.d_obj]--; 409 if (wrap_class_instances!(T)[self.d_obj] <= 0) { 410 wrap_class_instances!(T).remove(self.d_obj); 411 } 412 } 413 self.d_obj = t; 414 // Handle the new one, if there is one 415 if (t !is null) wrap_class_instances!(T)[t]++; 416 } trunk/infrastructure/pyd/ctor_wrap.d
r28 r37 83 83 int len = PyObject_Length(args); 84 84 85 try { 86 87 T t; 88 // Default ctor 89 static if (is(typeof(new T))) { 90 if (len == 0) { 91 t = new T; 92 goto Done; 85 return exception_catcher({ 86 // Default ctor 87 static if (is(typeof(new T))) { 88 if (len == 0) { 89 WrapPyObject_SetObj(self, new T); 90 return 0; 91 } 93 92 } 94 }95 // We only match the first supplied ctor with the proper number of96 // 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 functions102 // that call a constructor with its passed arguments, and103 // return the new object.104 // 2) instant_from_tuple is a template that instantiates a105 // template with the types in the passed tuple type. By106 // combining call_ctor with the selected tuple representing107 // the best match of constructor, we can get something like108 // a pointer to a constructor function.109 // 3) This function pointer is sent off to py_call, which calls110 // 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;93 // We only match the first supplied ctor with the proper number of 94 // arguments. (Eventually, we'll do some more sophisticated matching, 95 // but this will do for now.) 96 static if (ARGS >= 1) { 97 if (len == TypeNo!(Tuple, 0).length) { 98 // This works thusly: 99 // 1) outer!(T).call_ctor is a series of template functions 100 // that call a constructor with its passed arguments, and 101 // return the new object. 102 // 2) instant_from_tuple is a template that instantiates a 103 // template with the types in the passed tuple type. By 104 // combining call_ctor with the selected tuple representing 105 // the best match of constructor, we can get something like 106 // a pointer to a constructor function. 107 // 3) This function pointer is sent off to py_call, which calls 108 // it with the PyTuple that args points to. 109 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 0) ) fn1; 110 WrapPyObject_SetObj(self, py_call( &fn1, args )); 111 return 0; 112 } 114 113 } 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;114 static if (ARGS >= 2) { 115 if (len == TypeNo!(Tuple, 1).length) { 116 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 1) ) fn2; 117 WrapPyObject_SetObj(self, py_call( &fn2, args )); 118 return 0; 119 } 121 120 } 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;121 static if (ARGS >= 3) { 122 if (len == TypeNo!(Tuple, 2).length) { 123 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 2) ) fn3; 124 WrapPyObject_SetObj(self, py_call( &fn3, args )); 125 return 0; 126 } 128 127 } 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;128 static if (ARGS >= 4) { 129 if (len == TypeNo!(Tuple, 3).length) { 130 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 3) ) fn4; 131 WrapPyObject_SetObj(self, py_call( &fn4, args )); 132 return 0; 133 } 135 134 } 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;135 static if (ARGS >= 5) { 136 if (len == TypeNo!(Tuple, 4).length) { 137 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 4) ) fn5; 138 WrapPyObject_SetObj(self, py_call( &fn5, args )); 139 return 0; 140 } 142 141 } 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;142 static if (ARGS >= 6) { 143 if (len == TypeNo!(Tuple, 5).length) { 144 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 5) ) fn6; 145 WrapPyObject_SetObj(self, py_call( &fn6, args )); 146 return 0; 147 } 149 148 } 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;149 static if (ARGS >= 7) { 150 if (len == TypeNo!(Tuple, 6).length) { 151 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 6) ) fn7; 152 WrapPyObject_SetObj(self, py_call( &fn7, args )); 153 return 0; 154 } 156 155 } 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;156 static if (ARGS >= 8) { 157 if (len == TypeNo!(Tuple, 7).length) { 158 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 7) ) fn8; 159 WrapPyObject_SetObj(self, py_call( &fn8, args )); 160 return 0; 161 } 163 162 } 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;163 static if (ARGS >= 9) { 164 if (len == TypeNo!(Tuple, 8).length) { 165 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 8) ) fn9; 166 WrapPyObject_SetObj(self, py_call( &fn9, args )); 167 return 0; 168 } 170 169 } 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; 170 static if (ARGS >= 10) { 171 if (len == TypeNo!(Tuple, 9).length) { 172 alias instant_from_tuple!( outer!(T).call_ctor, TypeNo!(Tuple, 9) ) fn10; 173 WrapPyObject_SetObj(self, py_call( &fn10, args )); 174 return 0; 175 } 176 } else { 177 PyErr_SetString(PyExc_TypeError, "Unsupported number of constructor arguments."); 178 return -1; 177 179 } 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]++; 185 186 } /* end try */ 187 188 // A Python exception was raised and duly re-thrown as a D exception. 189 // It should now be re-raised as a Python exception. 190 catch (PythonException e) { 191 PyErr_Restore(e.type(), e.value(), e.traceback()); 192 return -1; 193 } 194 // A D exception was raised and should be translated into a meaningful 195 // Python exception. 196 catch (Exception e) { 197 PyErr_SetString(PyExc_RuntimeError, "D Exception: " ~ e.classinfo.name ~ ": " ~ e.msg ~ \0); 198 return -1; 199 } 200 201 return 0; 180 }); 202 181 } 203 182 } trunk/infrastructure/pyd/exception.d
r24 r37 29 29 * is) pulls it out, stuffs it in a PythonException, and throws that exception. 30 30 * 31 * If this exception is never caught, it will be handled by the function 32 * wrapping template and passed right back into Python as though nothing 33 * happened. 31 * If this exception is never caught, it will be handled by exception_catcher 32 * (below) and passed right back into Python as though nothing happened. 34 33 */ 35 34 void handle_exception() { … … 38 37 PyErr_Fetch(&type, &value, &traceback); 39 38 throw new PythonException(type, value, traceback); 39 } 40 } 41 42 /** 43 * It is intended that any functions that interface directly with Python which 44 * have the possibility of a D exception being raised wrap their contents in a 45 * call to this function, e.g.: 46 * 47 *$(D_CODE extern (C) 48 *PyObject* some_func(PyObject* self) { 49 * return _exception_catcher({ 50 * // ... 51 * }); 52 *}) 53 */ 54 PyObject* exception_catcher(PyObject* delegate() dg) { 55 try { 56 return dg(); 57 } 58 // A Python exception was raised and duly re-thrown as a D exception. 59 // It should now be re-raised as a Python exception. 60 catch (PythonException e) { 61 PyErr_Restore(e.type(), e.value(), e.traceback()); 62 return null; 63 } 64 // A D exception was raised and should be translated into a meaningful 65 // Python exception. 66 catch (Exception e) { 67 PyErr_SetString(PyExc_RuntimeError, "D Exception: " ~ e.classinfo.name ~ ": " ~ e.msg ~ \0); 68 return null; 69 } 70 // Some other D object was thrown. Deal with it. 71 catch (Object o) { 72 PyErr_SetString(PyExc_RuntimeError, "thrown D Object: " ~ o.classinfo.name ~ ": " ~ o.toString() ~ \0); 73 return null; 74 } 75 } 76 77 // XXX: Some way to combine this with the above? 78 int exception_catcher(int delegate() dg) { 79 try { 80 return dg(); 81 } 82 // A Python exception was raised and duly re-thrown as a D exception. 83 // It should now be re-raised as a Python exception. 84 catch (PythonException e) { 85 PyErr_Restore(e.type(), e.value(), e.traceback()); 86 return -1; 87 } 88 // A D exception was raised and should be translated into a meaningful 89 // Python exception. 90 catch (Exception e) { 91 PyErr_SetString(PyExc_RuntimeError, "D Exception: " ~ e.classinfo.name ~ ": " ~ e.msg ~ \0); 92 return -1; 93 } 94 // Some other D object was thrown. Deal with it. 95 catch (Object o) { 96 PyErr_SetString(PyExc_RuntimeError, "thrown D Object: " ~ o.classinfo.name ~ ": " ~ o.toString() ~ \0); 97 return -1; 40 98 } 41 99 } trunk/infrastructure/pyd/func_wrap.d
r28 r37 42 42 type.tp_basicsize = obj.sizeof; 43 43 type.tp_name = "DPyFunc"; 44 type.tp_call = &wrapped_func_call!(T /*, MIN_ARGS*/).call;44 type.tp_call = &wrapped_func_call!(T).call; 45 45 PyType_Ready(&type); 46 46 is_wrapped!(T) = true; … … 112 112 } 113 113 114 template wrapped_func_call(fn_t /*, uint MIN_ARGS*/) {114 template wrapped_func_call(fn_t) { 115 115 const uint MAX_ARGS = NumberOfArgs!(fn_t); 116 116 alias ReturnType!(fn_t) RetType; 117 // The entry for the tp_call slot of the DPyFunc types. 118 // (Or: What gets called when you pass a delegate or function pointer to 119 // Python.) 117 120 extern(C) 118 121 PyObject* call(PyObject* self, PyObject* args, PyObject* kwds) { … … 123 126 124 127 fn_t fn = (cast(wrapped_class_object!(fn_t)*)self).d_obj; 125 PyObject* ret;126 127 try{128 //PyObject* ret; 129 130 return exception_catcher({ 128 131 static if (is(RetType == void)) { 129 py_call /+!(fn_t/*, MIN_ARGS*/)+/(fn, args);132 py_call(fn, args); 130 133 Py_INCREF(Py_None); 131 ret =Py_None;134 return Py_None; 132 135 } else { 133 ret = _py( py_call/+!(fn_t/*, MIN_ARGS*/)+/(fn, args) );136 return _py( py_call(fn, args) ); 134 137 } 135 } 136 137 // A Python exception was raised and duly re-thrown as a D exception. 138 // It should now be re-raised as a Python exception. 139 catch (PythonException e) { 140 PyErr_Restore(e.type(), e.value(), e.traceback()); 141 return null; 142 } 143 // A D exception was raised and should be translated into a meaningful 144 // Python exception. 145 catch (Exception e) { 146 PyErr_SetString(PyExc_RuntimeError, "D Exception: " ~ e.classinfo.name ~ ": " ~ e.msg ~ \0); 147 return null; 148 } 149 return ret; 138 }); 150 139 } 151 140 } … … 214 203 extern (C) 215 204 PyObject* func(PyObject* self, PyObject* args) { 216 try { 205 // For some reason, D can't infer the return type of this function 206 // literal... 207 return exception_catcher(delegate PyObject*() { 217 208 // If C is specified, then this is a method call. We need to pull out 218 209 // the object in self and turn the member function pointer in real_fn … … 239 230 return tuple_py_call(func_range!(real_fn, MIN_ARGS)(), args); 240 231 } 241 } 242 243 // A Python exception was raised and duly re-thrown as a D exception. 244 // It should now be re-raised as a Python exception. 245 catch (PythonException e) { 246 PyErr_Restore(e.type(), e.value(), e.traceback()); 247 return null; 248 } 249 // A D exception was raised and should be translated into a meaningful 250 // Python exception. 251 catch (Exception e) { 252 PyErr_SetString(PyExc_RuntimeError, "D Exception: " ~ e.classinfo.name ~ ": " ~ e.msg ~ \0); 253 return null; 254 } 255 //return wrapped_func_call!(typeof(fn), MIN_ARGS).call(cast(PyObject*)&fn_obj, args, null); 232 }); 256 233 } 257 234 } trunk/infrastructure/pyd/make_object.d
r29 r37 63 63 } 64 64 65 ///66 template _py(T) {67 65 /** 68 66 * Returns a new (owned) reference to a Python object based on the passed … … 75 73 * RuntimeError will be raised and this function will return null. 76 74 */ 77 // I reverted these to the old-style function templates as ddoc can't seem to 78 // handle the new style. 79 //PyObject* _py(T) (T t) { 80 PyObject* _py(T t) { 75 PyObject* _py(T) (T t) { 81 76 static if (is(T : bool)) { 82 77 PyObject* temp = (t) ? Py_True : Py_False; … … 146 141 // Put only if it actually is a wrapped type. :-) 147 142 if (is_wrapped!(T)) { 148 // Allocate the object 149 wrapped_class_object!(T)* obj = 150 cast(wrapped_class_object!(T)*)wrapped_class_type!(T).tp_new(&wrapped_class_type!(T), null, null); 151 obj.d_obj = t; 152 // Add the reference to the class's reference AA to help keep the 153 // GC happy. 154 if (t in wrap_class_instances!(T)) { 155 wrap_class_instances!(T)[t] = wrap_class_instances!(T)[t] + 1; 156 } else { 157 wrap_class_instances!(T)[t] = 1; 158 } 159 return cast(PyObject*)obj; 143 return WrapPyObject_FromObject(t); 160 144 } 161 145 // If it's not a wrapped type, fall through to the exception. … … 168 152 return null; 169 153 } 170 } /* end template _py */ 171 172 /// 173 template py(T) { 154 174 155 /** 175 156 * Constructs an object based on the type of the argument passed in. … … 182 163 * Calling this with a PyObject* will "steal" the reference. 183 164 */ 184 // I reverted these to the old-style function templates as ddoc can't seem to 185 // handle the new style. 186 //DPyObject py(T) (T t) { 187 DPyObject py(T t) { 165 DPyObject py(T) (T t) { 188 166 static if(is(T : DPyObject)) { 189 167 return t; … … 192 170 } 193 171 } 194 } /* end template py */195 172 196 173 /** … … 201 178 } 202 179 203 ///204 template d_type(T) {205 180 /** 206 181 * This converts a PyObject* to a D type. The template argument is the type to … … 214 189 * the given D type. 215 190 */ 216 // I reverted these to the old-style function templates as ddoc can't seem to 217 // handle the new style. 218 //T d_type(T) (PyObject* o) { 219 T d_type(PyObject* o) { 191 T d_type(T) (PyObject* o) { 220 192 // This ordering is very important. If the check for bool came first, 221 193 // then all integral types would be converted to bools (they would be … … 240 212 // we can only convert the object if it is the wrapped type. 241 213 if (is_wrapped!(T) && PyObject_TypeCheck(o, &wrapped_class_type!(T))) { 242 return (cast(wrapped_class_object!(T)*)o).d_obj;214 return WrapPyObject_AsObject!(T)(o); 243 215 } 244 216 // Otherwise, throw up an exception. … … 299 271 } 300 272 } 301 } /* end template d_type */302 273 303 274 private trunk/infrastructure/pyd/op_wrap.d
r28 r37 331 331 332 332 template opIn_wrap(T) { 333 static if (is(typeof(&T.opIn ))) {334 const binaryfunc opIn_wrap = &opfunc_binary_wrap!(T, T.opIn ).func;333 static if (is(typeof(&T.opIn_r))) { 334 const binaryfunc opIn_wrap = &opfunc_binary_wrap!(T, T.opIn_r).func; 335 335 } else { 336 336 const binaryfunc opIn_wrap = null;
