Changeset 66
- Timestamp:
- 12/19/06 01:20:30 (2 years ago)
- Files:
-
- trunk/examples/testdll/test.py (modified) (1 diff)
- trunk/examples/testdll/testdll.d (modified) (1 diff)
- trunk/infrastructure/pyd/class_wrap.d (modified) (6 diffs)
- trunk/infrastructure/pyd/func_wrap.d (modified) (3 diffs)
- trunk/infrastructure/pyd/make_object.d (modified) (2 diffs)
- trunk/infrastructure/pyd/pydobject.d (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/examples/testdll/test.py
r61 r66 28 28 print 29 29 30 print "Testing callback support" 31 def foo(): 32 print "Callback works!" 33 testdll.dg_test(foo) 34 print "Testing delegate wrapping" 35 dg = testdll.func_test() 36 dg() 37 38 print 39 30 40 a = testdll.Foo(10) 31 41 a.foo() trunk/examples/testdll/testdll.d
r64 r66 88 88 89 89 void delegate() func_test() { 90 Foo f = new Foo(20); 91 return &f.foo; 90 return { writefln("Delegate works!"); }; 92 91 } 93 92 trunk/infrastructure/pyd/class_wrap.d
r59 r66 111 111 } 112 112 113 // A mapp ing of all objects referenced by the GCthat are being held by Python.113 // A mappnig of all class references that are being held by Python. 114 114 PyObject*[void*] wrapped_gc_objects; 115 // A mapping of all GC references that are being held by Python. 116 template wrapped_gc_references(dg_t) { 117 PyObject*[dg_t] wrapped_gc_references; 118 } 115 119 116 120 /** … … 453 457 python.PyObject* _pyobj = wrapped_gc_objects[cast(void*)this]; 454 458 if (_pyobj.ob_type != &wrapped_class_type!(typeof(this))) { 455 //writefln("Wrapper class, calling wrapped PyObject");456 459 // If this object's type is not the wrapped class's type (that is, 457 460 // if this object is actually a Python subclass of the wrapped … … 463 466 return pydg(t); 464 467 } else { 465 //writefln("Wrapper class, calling original delegate");466 468 return dg(t); 467 469 } … … 485 487 } else { 486 488 return cast(void*)t; 489 } 490 } 491 492 // If the passed D reference has an existing Python object, return a borrowed 493 // reference to it. Otherwise, return null. 494 PyObject* get_existing_reference(T) (T t) { 495 static if (is(T == class)) { 496 PyObject** obj_p = cast(void*)t in wrapped_gc_objects; 497 if (obj_p) return *obj_p; 498 else return null; 499 } else { 500 PyObject** obj_p = t in wrapped_gc_references!(T); 501 if (obj_p) return *obj_p; 502 else return null; 503 } 504 } 505 506 // Drop the passed D reference from the pool of held references. 507 void drop_reference(T) (T t) { 508 static if (is(T == class)) { 509 wrapped_gc_objects.remove(cast(void*)t); 510 } else { 511 wrapped_gc_references!(T).remove(t); 512 } 513 } 514 515 // Add the passed D reference to the pool of held references. 516 void add_reference(T) (T t, PyObject* o) { 517 static if (is(T == class)) { 518 wrapped_gc_objects[cast(void*)t] = o; 519 } else { 520 wrapped_gc_references!(T)[t] = o; 487 521 } 488 522 } … … 496 530 if (is_wrapped!(T)) { 497 531 // If this object is already wrapped, get the existing object. 498 PyObject** obj_p = get_voidptr(t) in wrapped_gc_objects; 499 if (obj_p) return *obj_p; 532 PyObject* obj_p = get_existing_reference(t); 533 if (obj_p) { 534 Py_INCREF(obj_p); 535 return obj_p; 536 } 500 537 // Otherwise, allocate a new object 501 538 PyObject* obj = type.tp_new(&type, null, null); … … 528 565 alias wrapped_class_object!(T) obj; 529 566 obj* self = cast(obj*)_self; 530 if (get_voidptr(t) == get_voidptr(self.d_obj)) 531 return; 567 if (t is self.d_obj) return; 532 568 // Clean up the old object, if there is one 533 569 if (self.d_obj !is null) { 534 wrapped_gc_objects.remove(get_voidptr(self.d_obj));570 drop_reference(self.d_obj); 535 571 } 536 572 self.d_obj = t; 537 573 // Handle the new one, if there is one 538 if (t !is null) wrapped_gc_objects[get_voidptr(self.d_obj)] = _self;539 } 540 574 if (t !is null) add_reference(self.d_obj, _self); 575 } 576 trunk/infrastructure/pyd/func_wrap.d
r57 r66 46 46 type.tp_basicsize = obj.sizeof; 47 47 type.tp_name = "PydFunc"; 48 type.tp_flags = Py_TPFLAGS_DEFAULT; 48 49 49 50 type.tp_call = &wrapped_func_call!(T).call; … … 101 102 argCount = PyObject_Length(args); 102 103 } 103 //writefln("argCount: %s; MIN_ARGS: %s; MAX_ARGS: %s", argCount, MIN_ARGS, MAX_ARGS);104 104 105 105 // Sanity check! … … 291 291 PyObject* call(T ...) (T t) { 292 292 const uint ARGS = T.length; 293 294 PyObject* pyt = PyTuple_New(ARGS); 293 PyObject* pyt = PyTuple_FromItems(t); 295 294 if (pyt is null) return null; 296 295 scope(exit) Py_DECREF(pyt); 297 298 foreach(i, arg; t) {299 PyTuple_SetItem(pyt, i, _py(arg));300 }301 296 return PyObject_CallObject(callable, pyt); 302 297 } trunk/infrastructure/pyd/make_object.d
r54 r66 278 278 +/ 279 279 } else static if (is(char[] : T)) { 280 //writefln("d_type!(char[])");281 280 char* result; 282 281 PyObject* repr; … … 292 291 } 293 292 if (result is null) handle_exception(); 294 //char[] s = .toString(result);295 //writefln("result is |%s|", result);296 //writefln("s is |%s|", s);297 293 return .toString(result).dup; 298 294 } else static if (is(cdouble : T)) { trunk/infrastructure/pyd/pydobject.d
r54 r66 200 200 201 201 /** 202 * Calls the PydObject .202 * Calls the PydObject with the PyTuple args. 203 203 * Params: 204 204 * args = Should be a PydTuple of the arguments to pass. Omit to … … 206 206 * Returns: Whatever the function PydObject returns. 207 207 */ 208 PydObject opCall(PydObject args=null) {208 PydObject unpackCall(PydObject args=null) { 209 209 return new PydObject(PyObject_CallObject(m_ptr, args is null ? null : args.m_ptr)); 210 210 } … … 218 218 * Returns: Whatever the function PydObject returns. 219 219 */ 220 PydObject opCall(PydObject args, PydObject kw) {220 PydObject unpackCall(PydObject args, PydObject kw) { 221 221 return new PydObject(PyObject_Call(m_ptr, args.m_ptr, kw.m_ptr)); 222 222 } 223 223 224 224 /** 225 * Calls the PydObject with any convertible D items. 226 */ 227 PydObject opCall(T ...) (T t) { 228 PyObject* tuple = PyTuple_FromItems(t); 229 if (tuple is null) handle_exception(); 230 PyObject* result = PyObject_CallObject(m_ptr, tuple); 231 Py_DECREF(tuple); 232 if (result is null) handle_exception(); 233 return new PydObject(result); 234 } 235 236 /** 225 237 * 226 238 */ 227 PydObject method (char[] name, PydObject args=null) {239 PydObject methodUnpack(char[] name, PydObject args=null) { 228 240 // Get the method PydObject 229 241 PyObject* m = PyObject_GetAttrString(m_ptr, (name ~ \0).ptr); 230 PyObject* self_tuple, args_tuple,result;242 PyObject* result; 231 243 // If this method doesn't exist (or other error), throw exception 232 244 if (m is null) handle_exception(); 233 // Set up a tuple with (self,)234 self_tuple = PyTuple_Pack(1, m_ptr);235 if (self_tuple is null) handle_exception();236 // If there are additional arguments, concat them onto (self,)237 if (args !is null) {238 args_tuple = PySequence_Concat(self_tuple, args.m_ptr);239 Py_DECREF(self_tuple);240 self_tuple = null;241 // Otherwise, just use (self,)242 } else {243 args_tuple = self_tuple;244 self_tuple = null;245 }246 245 // Call the method, and decrement the refcounts on the temporaries. 247 result = PyObject_CallObject(m, args _tuple);246 result = PyObject_CallObject(m, args is null ? null : args.m_ptr); 248 247 Py_DECREF(m); 249 Py_DECREF(args_tuple);250 248 // Return the result. 251 249 return new PydObject(result); 252 250 } 253 251 254 PydObject method (char[] name, PydObject args, PydObject kw) {252 PydObject methodUnpack(char[] name, PydObject args, PydObject kw) { 255 253 // Get the method PydObject 256 254 PyObject* m = PyObject_GetAttrString(m_ptr, (name ~ \0).ptr); 257 PyObject* self_tuple, args_tuple,result;255 PyObject* result; 258 256 // If this method doesn't exist (or other error), throw exception. 259 257 if (m is null) handle_exception(); 260 // Set up a tuple with (self,)261 self_tuple = PyTuple_Pack(1, m_ptr);262 if (self_tuple is null) handle_exception();263 // Put "self" at the beginning of the argument list.264 args_tuple = PySequence_Concat(self_tuple, args.m_ptr);265 Py_DECREF(self_tuple);266 self_tuple = null;267 258 // Call the method, and decrement the refcounts on the temporaries. 268 result = PyObject_Call(m, args _tuple, kw.m_ptr);259 result = PyObject_Call(m, args.m_ptr, kw.m_ptr); 269 260 Py_DECREF(m); 270 Py_DECREF(args_tuple);271 261 // Return the result. 262 return new PydObject(result); 263 } 264 265 /** 266 * Calls a method of the object with any convertible D items. 267 */ 268 PydObject method(T ...) (char[] name, T t) { 269 PyObject* mthd = PyObject_GetAttrString(m_ptr, (name ~ \0).ptr); 270 if (mthd is null) handle_exception(); 271 PyObject* tuple = PyTuple_FromItems(t); 272 if (tuple is null) { 273 Py_DECREF(mthd); 274 handle_exception(); 275 } 276 PyObject* result = PyObject_CallObject(mthd, tuple); 277 Py_DECREF(mthd); 278 Py_DECREF(tuple); 279 if (result is null) handle_exception(); 272 280 return new PydObject(result); 273 281 } … … 278 286 if (res == -1) handle_exception(); 279 287 return res; 288 } 289 290 T toDItem(T)() { 291 return d_type!(T)(m_ptr); 280 292 } 281 293
