Changeset 37

Show
Ignore:
Timestamp:
08/14/06 21:41:17 (2 years ago)
Author:
KirkMcDonald
Message:

opApply wrapping and various refactoring

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/dcompiler.py

    r30 r37  
    3434    'ftype.d', 
    3535    'func_wrap.d', 
     36    'iteration.d', 
    3637    'make_object.d', 
    3738    'op_wrap.d', 
    3839    'pyd.d', 
    3940    'tuples.d', 
     41] 
     42 
     43_stFiles = [ 
     44    'coroutine.d', 
     45    'stackcontext.d', 
     46    'stackthread.d', 
    4047] 
    4148 
     
    125132        binpath = _qp(self._binpath) 
    126133        compileOpts = self._compileOpts 
    127         #outputOpts = self._outputOpts 
     134        outputOpts = self._outputOpts 
    128135 
    129136        includePathOpts = [] 
     
    150157                ) 
    151158            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 
    153168        includePathOpts += self._includeOpts 
    154169        includePathOpts[-1] = includePathOpts[-1] % os.path.join(_infraDir) 
     
    199214            optimizationOpts = self._defaultOptimizeOpts 
    200215 
    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) 
    227256            os.chdir(cwd) 
    228             raise CompileError(msg) 
    229         os.chdir(cwd) 
    230257 
    231258        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  
    3131a.foo() 
    3232 
     33print "Testing opApply wrapping:" 
     34for i in a: 
     35    print i 
     36 
    3337print 
    3438 
  • trunk/examples/testdll/testdll.d

    r28 r37  
    5353    } 
    5454    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    } 
    5563    int i() { return m_i; } 
    5664    void i(int j) { m_i = j; } 
  • trunk/infrastructure/pyd/class_wrap.d

    r28 r37  
    2626private import pyd.ctor_wrap; 
    2727private import pyd.def; 
     28private import pyd.exception; 
    2829private import pyd.ftype; 
    2930private import pyd.func_wrap; 
     31private import pyd.iteration; 
    3032private import pyd.make_object; 
    3133private import pyd.op_wrap; 
     
    111113    extern(C) 
    112114    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        }); 
    121125    } 
    122126 
    123127    /// The generic dealloc method. 
    124128    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        }); 
    134135    } 
    135136} 
     
    140141    extern(C) 
    141142    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        }); 
    145148    } 
    146149} 
     
    152155    extern(C) 
    153156    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        })
    158161    } 
    159162} 
     
    182185    extern(C) 
    183186    PyObject* func(PyObject* self, void* closure) { 
     187        // func_wrap already catches exceptions 
    184188        return func_wrap!(Fn, 0, T, property_parts!(Fn).getter_type).func(self, null); 
    185189    } 
     
    193197        PyObject* temp_tuple = PyTuple_New(1); 
    194198        if (temp_tuple is null) return -1; 
     199        scope(exit) Py_DECREF(temp_tuple); 
    195200        Py_INCREF(value); 
    196201        PyTuple_SetItem(temp_tuple, 0, value); 
    197202        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. 
    201208        return 0; 
    202209    } 
     
    341348        type.tp_as_number = &wrapped_class_as_number!(T); 
    342349    } 
     350 
     351    static if (is(typeof(&T.opApply))) { 
     352        DPySC_Ready(); 
     353        type.tp_iter = &wrapped_iter!(T).iter; 
     354    } 
    343355     
    344356    // If a ctor wasn't supplied, try the default. 
     
    356368    wrapped_classes[typeid(T)] = true; 
    357369} 
     370 
     371/** 
     372 * Returns a new Python object of a wrapped type. 
     373 */ 
     374PyObject* 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 
     390T 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 */ 
     403void 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  
    8383        int len = PyObject_Length(args); 
    8484 
    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                } 
    9392            } 
    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; 
     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                } 
    114113            } 
    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                } 
    121120            } 
    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                } 
    128127            } 
    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                } 
    135134            } 
    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                } 
    142141            } 
    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                } 
    149148            } 
    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                } 
    156155            } 
    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                } 
    163162            } 
    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                } 
    170169            } 
    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; 
    177179            } 
    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        }); 
    202181    } 
    203182} 
  • trunk/infrastructure/pyd/exception.d

    r24 r37  
    2929 * is) pulls it out, stuffs it in a PythonException, and throws that exception. 
    3030 * 
    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. 
    3433 */ 
    3534void handle_exception() { 
     
    3837        PyErr_Fetch(&type, &value, &traceback); 
    3938        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 */ 
     54PyObject* 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? 
     78int 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; 
    4098    } 
    4199} 
  • trunk/infrastructure/pyd/func_wrap.d

    r28 r37  
    4242            type.tp_basicsize = obj.sizeof; 
    4343            type.tp_name = "DPyFunc"; 
    44             type.tp_call = &wrapped_func_call!(T/*, MIN_ARGS*/).call; 
     44            type.tp_call = &wrapped_func_call!(T).call; 
    4545            PyType_Ready(&type); 
    4646            is_wrapped!(T) = true; 
     
    112112} 
    113113 
    114 template wrapped_func_call(fn_t/*, uint MIN_ARGS*/) { 
     114template wrapped_func_call(fn_t) { 
    115115    const uint MAX_ARGS = NumberOfArgs!(fn_t); 
    116116    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.) 
    117120    extern(C) 
    118121    PyObject* call(PyObject* self, PyObject* args, PyObject* kwds) { 
     
    123126 
    124127        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(
    128131            static if (is(RetType == void)) { 
    129                 py_call/+!(fn_t/*, MIN_ARGS*/)+/(fn, args); 
     132                py_call(fn, args); 
    130133                Py_INCREF(Py_None); 
    131                 ret = Py_None; 
     134                return Py_None; 
    132135            } else { 
    133                 ret = _py( py_call/+!(fn_t/*, MIN_ARGS*/)+/(fn, args) ); 
     136                return _py( py_call(fn, args) ); 
    134137            } 
    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        }); 
    150139    } 
    151140} 
     
    214203    extern (C) 
    215204    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*() { 
    217208            // If C is specified, then this is a method call. We need to pull out 
    218209            // the object in self and turn the member function pointer in real_fn 
     
    239230                return tuple_py_call(func_range!(real_fn, MIN_ARGS)(), args); 
    240231            } 
    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        }); 
    256233    } 
    257234} 
  • trunk/infrastructure/pyd/make_object.d

    r29 r37  
    6363} 
    6464 
    65 /// 
    66 template _py(T) { 
    6765/** 
    6866 * Returns a new (owned) reference to a Python object based on the passed 
     
    7573 * RuntimeError will be raised and this function will return null. 
    7674 */ 
    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) { 
     75PyObject* _py(T) (T t) { 
    8176    static if (is(T : bool)) { 
    8277        PyObject* temp = (t) ? Py_True : Py_False; 
     
    146141        // Put only if it actually is a wrapped type. :-) 
    147142        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); 
    160144        } 
    161145        // If it's not a wrapped type, fall through to the exception. 
     
    168152    return null; 
    169153} 
    170 } /* end template _py */ 
    171  
    172 /// 
    173 template py(T) { 
     154 
    174155/** 
    175156 * Constructs an object based on the type of the argument passed in. 
     
    182163 * Calling this with a PyObject* will "steal" the reference. 
    183164 */ 
    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) { 
     165DPyObject py(T) (T t) { 
    188166    static if(is(T : DPyObject)) { 
    189167        return t; 
     
    192170    } 
    193171} 
    194 } /* end template py */ 
    195172 
    196173/** 
     
    201178} 
    202179 
    203 /// 
    204 template d_type(T) { 
    205180/** 
    206181 * This converts a PyObject* to a D type. The template argument is the type to 
     
    214189 * the given D type. 
    215190 */ 
    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) { 
     191T d_type(T) (PyObject* o) { 
    220192    // This ordering is very important. If the check for bool came first, 
    221193    // then all integral types would be converted to bools (they would be 
     
    240212        // we can only convert the object if it is the wrapped type. 
    241213        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)
    243215        } 
    244216        // Otherwise, throw up an exception. 
     
    299271    } 
    300272} 
    301 } /* end template d_type */ 
    302273 
    303274private 
  • trunk/infrastructure/pyd/op_wrap.d

    r28 r37  
    331331 
    332332template 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; 
    335335    } else { 
    336336        const binaryfunc opIn_wrap = null;