Changeset 66

Show
Ignore:
Timestamp:
12/19/06 01:20:30 (2 years ago)
Author:
KirkMcDonald
Message:

Reference-keeping improvements; delegate-wrapping bugfixes; PydObject? improvements

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/examples/testdll/test.py

    r61 r66  
    2828print 
    2929 
     30print "Testing callback support" 
     31def foo(): 
     32    print "Callback works!" 
     33testdll.dg_test(foo) 
     34print "Testing delegate wrapping" 
     35dg = testdll.func_test() 
     36dg() 
     37 
     38print 
     39 
    3040a = testdll.Foo(10) 
    3141a.foo() 
  • trunk/examples/testdll/testdll.d

    r64 r66  
    8888 
    8989void delegate() func_test() { 
    90     Foo f = new Foo(20); 
    91     return &f.foo; 
     90    return { writefln("Delegate works!"); }; 
    9291} 
    9392 
  • trunk/infrastructure/pyd/class_wrap.d

    r59 r66  
    111111} 
    112112 
    113 // A mapping of all objects referenced by the GC that are being held by Python. 
     113// A mappnig of all class references that are being held by Python. 
    114114PyObject*[void*] wrapped_gc_objects; 
     115// A mapping of all GC references that are being held by Python. 
     116template wrapped_gc_references(dg_t) { 
     117    PyObject*[dg_t] wrapped_gc_references; 
     118} 
    115119 
    116120/** 
     
    453457        python.PyObject* _pyobj = wrapped_gc_objects[cast(void*)this]; 
    454458        if (_pyobj.ob_type != &wrapped_class_type!(typeof(this))) { 
    455             //writefln("Wrapper class, calling wrapped PyObject"); 
    456459            // If this object's type is not the wrapped class's type (that is, 
    457460            // if this object is actually a Python subclass of the wrapped 
     
    463466            return pydg(t); 
    464467        } else { 
    465             //writefln("Wrapper class, calling original delegate"); 
    466468            return dg(t); 
    467469        } 
     
    485487    } else { 
    486488        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. 
     494PyObject* 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. 
     507void 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. 
     516void 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; 
    487521    } 
    488522} 
     
    496530    if (is_wrapped!(T)) { 
    497531        // 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        } 
    500537        // Otherwise, allocate a new object 
    501538        PyObject* obj = type.tp_new(&type, null, null); 
     
    528565    alias wrapped_class_object!(T) obj; 
    529566    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; 
    532568    // Clean up the old object, if there is one 
    533569    if (self.d_obj !is null) { 
    534         wrapped_gc_objects.remove(get_voidptr(self.d_obj)); 
     570        drop_reference(self.d_obj); 
    535571    } 
    536572    self.d_obj = t; 
    537573    // 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  
    4646        type.tp_basicsize = obj.sizeof; 
    4747        type.tp_name = "PydFunc"; 
     48        type.tp_flags = Py_TPFLAGS_DEFAULT; 
    4849 
    4950        type.tp_call = &wrapped_func_call!(T).call; 
     
    101102        argCount = PyObject_Length(args); 
    102103    } 
    103     //writefln("argCount: %s; MIN_ARGS: %s; MAX_ARGS: %s", argCount, MIN_ARGS, MAX_ARGS); 
    104104 
    105105    // Sanity check! 
     
    291291    PyObject* call(T ...) (T t) { 
    292292        const uint ARGS = T.length; 
    293  
    294         PyObject* pyt = PyTuple_New(ARGS); 
     293        PyObject* pyt = PyTuple_FromItems(t); 
    295294        if (pyt is null) return null; 
    296295        scope(exit) Py_DECREF(pyt); 
    297  
    298         foreach(i, arg; t) { 
    299             PyTuple_SetItem(pyt, i, _py(arg)); 
    300         } 
    301296        return PyObject_CallObject(callable, pyt); 
    302297    } 
  • trunk/infrastructure/pyd/make_object.d

    r54 r66  
    278278    +/ 
    279279    } else static if (is(char[] : T)) { 
    280         //writefln("d_type!(char[])"); 
    281280        char* result; 
    282281        PyObject* repr; 
     
    292291        } 
    293292        if (result is null) handle_exception(); 
    294         //char[] s = .toString(result); 
    295         //writefln("result is |%s|", result); 
    296         //writefln("s is      |%s|", s); 
    297293        return .toString(result).dup; 
    298294    } else static if (is(cdouble : T)) { 
  • trunk/infrastructure/pyd/pydobject.d

    r54 r66  
    200200     
    201201    /** 
    202      * Calls the PydObject
     202     * Calls the PydObject with the PyTuple args
    203203     * Params: 
    204204     *      args = Should be a PydTuple of the arguments to pass. Omit to 
     
    206206     * Returns: Whatever the function PydObject returns. 
    207207     */ 
    208     PydObject opCall(PydObject args=null) { 
     208    PydObject unpackCall(PydObject args=null) { 
    209209        return new PydObject(PyObject_CallObject(m_ptr, args is null ? null : args.m_ptr)); 
    210210    } 
     
    218218     * Returns: Whatever the function PydObject returns. 
    219219     */ 
    220     PydObject opCall(PydObject args, PydObject kw) { 
     220    PydObject unpackCall(PydObject args, PydObject kw) { 
    221221        return new PydObject(PyObject_Call(m_ptr, args.m_ptr, kw.m_ptr)); 
    222222    } 
    223223 
    224224    /** 
     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    /** 
    225237     * 
    226238     */ 
    227     PydObject method(char[] name, PydObject args=null) { 
     239    PydObject methodUnpack(char[] name, PydObject args=null) { 
    228240        // Get the method PydObject 
    229241        PyObject* m = PyObject_GetAttrString(m_ptr, (name ~ \0).ptr); 
    230         PyObject* self_tuple, args_tuple, result; 
     242        PyObject* result; 
    231243        // If this method doesn't exist (or other error), throw exception 
    232244        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         } 
    246245        // 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); 
    248247        Py_DECREF(m); 
    249         Py_DECREF(args_tuple); 
    250248        // Return the result. 
    251249        return new PydObject(result); 
    252250    } 
    253251 
    254     PydObject method(char[] name, PydObject args, PydObject kw) { 
     252    PydObject methodUnpack(char[] name, PydObject args, PydObject kw) { 
    255253        // Get the method PydObject 
    256254        PyObject* m = PyObject_GetAttrString(m_ptr, (name ~ \0).ptr); 
    257         PyObject* self_tuple, args_tuple, result; 
     255        PyObject* result; 
    258256        // If this method doesn't exist (or other error), throw exception. 
    259257        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; 
    267258        // 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); 
    269260        Py_DECREF(m); 
    270         Py_DECREF(args_tuple); 
    271261        // 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(); 
    272280        return new PydObject(result); 
    273281    } 
     
    278286        if (res == -1) handle_exception(); 
    279287        return res; 
     288    } 
     289 
     290    T toDItem(T)() { 
     291        return d_type!(T)(m_ptr); 
    280292    } 
    281293