Changeset 28

Show
Ignore:
Timestamp:
07/12/06 19:24:58 (2 years ago)
Author:
KirkMcDonald
Message:

Function wrapping refactoring, now uses tuples.

Files:

Legend:

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

    r26 r28  
    3636    'op_wrap.d', 
    3737    'pyd.d', 
     38    'tuples.d', 
    3839] 
    3940 
  • trunk/examples/testdll/testdll.d

    r27 r28  
    33import python; 
    44import pyd.pyd; 
     5//import pyd.ftype; 
    56import std.stdio; 
    67 
    7 // d_type testing 
     8void apply_test(int i, char[] s) { 
     9    writefln("%s %s", i, s); 
     10
     11 
    812void foo() { 
    9     PyObject* s = PyString_FromString("blargh"); 
    10     PyObject* i = PyInt_FromLong(20); 
    11  
    12     int a = d_type!(int)(i); 
    13     char[] b = d_type!(char[])(s); 
    14  
    15     writefln("%s\n%s", a, b); 
    16  
    17     Py_DECREF(s); 
    18     Py_DECREF(i); 
     13    alias tuple!(int, char[]) Tuple; 
     14//    alias dg_from_tuple!(void, Tuple) dg; 
     15    Tuple t; 
     16//    Tuple.TypeNo!(0) i = 20; 
     17//    typeof(Tuple.arg1) j = 30; 
     18    t.arg1 = 20; 
     19    t.arg2 = "Monkey"; 
     20//    t.arg3 = 5.8; 
     21    apply_tuple_to_fn(t, &apply_test); 
     22     
     23//    writefln(typeid(ArgType!(dg, 1))); 
     24//    writefln(typeid(TypeNo!(Tuple, 0))); 
     25//    writefln(typeid(Tuple.A1)); 
     26//    writefln(typeid(dg)); 
     27//    writefln(i, " ", j); 
    1928} 
    2029 
     
    9099extern (C) 
    91100export void inittestdll() { 
     101    def!(foo, "foo"); 
     102    // Python does not support function overloading. This allows us to wrap 
     103    // an overloading function under a different name. Note that if the 
     104    // overload accepts a different number of minimum arguments, that number 
     105    // must be specified. 
     106    def!(foo, "foo2", void function(int), 1); 
     107    def!(bar, "bar"); 
     108    // Default argument support - Now implicit! 
     109    def!(baz, "baz"); 
     110    def!(spam, "spam"); 
     111    def!(iter_test, "iter_test"); 
     112    def!(func_test, "func_test"); 
     113    def!(dg_test, "dg_test"); 
     114 
    92115    module_init("testdll"); 
    93116 
    94     def!("foo", foo); 
    95     // Python does not support function overloading. This allows us to wrap 
    96     // an overloading function under a different name. 
    97     def!("foo2", foo, 1, void function(int)); 
    98     def!("bar", bar); 
    99     // Default argument support - Now implicit! 
    100     def!("baz", baz); 
    101     def!("spam", spam); 
    102     def!("iter_test", iter_test); 
    103     def!("func_test", func_test); 
    104     def!("dg_test", dg_test); 
     117    auto t = func_range!(foo, 0)(); 
     118    alias typeof(t) Tu; 
     119    writefln(typeid(TypeNo!(Tu, 1))); 
     120    writefln(MIN_ARGS!(bar)); 
    105121 
    106     wrapped_class!("Foo", Foo) f; 
     122    wrapped_class!(Foo, "Foo") f; 
    107123    // Constructor wrapping 
    108     f.init!(ctor!(int), ctor!(int, int)); 
     124    f.init!(tuple!(int), tuple!(int, int)); 
    109125    // Member function wrapping 
    110     f.def!("foo", Foo.foo); 
     126    f.def!(Foo.foo, "foo"); 
    111127    // Property wrapping 
    112     f.prop!("i", Foo.i); 
     128    f.prop!(Foo.i, "i"); 
    113129    finalize_class(f); 
    114130} 
  • trunk/infrastructure/pyd/class_wrap.d

    r27 r28  
    3030private import pyd.make_object; 
    3131private import pyd.op_wrap; 
     32private import pyd.tuples; 
    3233 
    3334private import std.string; 
     
    235236 * wrapping the specific parts of the class. 
    236237 */ 
    237 template wrapped_class(char[] classname, T) { 
     238template wrapped_class(T, char[] classname) { 
     239    pragma(msg, "wrapped_class: " ~ classname); 
    238240    struct wrapped_class { 
    239241        static const char[] _name = classname; 
     
    249251         *        if more than one function has the same name as this one. 
    250252         */ 
    251         template def(char[] name, alias fn, uint MIN_ARGS = MIN_ARGS!(fn), fn_t=typeof(&fn)) { 
     253        template def(alias fn, char[] name, fn_t=typeof(&fn), uint MIN_ARGS = MIN_ARGS!(fn)) { 
     254            pragma(msg, "class.def: " ~ name); 
    252255            static void def() { 
    253256                static PyMethodDef empty = { null, null, 0, null }; 
     
    272275         * RO = Whether this is a read-only property. 
    273276         */ 
    274         template prop(char[] name, alias fn, bool RO=false) { 
     277        template prop(alias fn, char[] name, bool RO=false) { 
     278            pragma(msg, "class.prop: " ~ name); 
    275279            static void prop() { 
    276280                static PyGetSetDef empty = { null, null, null, null, null }; 
     
    304308         * the same number of arguments. 
    305309         */ 
    306         template init(alias C1=undefined, alias C2=undefined, alias C3=undefined, alias C4=undefined, alias C5=undefined, alias C6=undefined, alias C7=undefined, alias C8=undefined, alias C9=undefined, alias C10=undefined) { 
     310        template init(C1=Void, C2=Void, C3=Void, C4=Void, C5=Void, C6=Void, C7=Void, C8=Void, C9=Void, C10=Void) { 
    307311            static void init() { 
    308312                wrapped_class_type!(T).tp_init = 
    309                     &wrapped_ctors!(T, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10).init_func; 
     313                    &wrapped_ctors!(T, tuple!(C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)).init_func; 
    310314            } 
    311315        } 
     
    321325    alias wrapped_class_type!(T) type; 
    322326    const char[] name = CLS._name; 
     327    pragma(msg, "finalize_class: " ~ name); 
    323328     
    324329    assert(DPy_Module_p !is null, "Must initialize module before wrapping classes."); 
  • trunk/infrastructure/pyd/ctor_wrap.d

    r25 r28  
    2525private import pyd.class_wrap; 
    2626private import pyd.exception; 
     27private import pyd.func_wrap; 
    2728private import pyd.make_object; 
    28  
    29 /** 
    30  * This template defines the footprint of an individual constructor. 
    31  */ 
    32 template ctor(T1=void, T2=void, T3=void, T4=void, T5=void, T6=void, T7=void, T8=void, T9=void, T10=void) { 
    33     static if (!is(T10 == void)) 
    34         const uint ARGS = 10; 
    35     else static if(!is(T9 == void)) 
    36         const uint ARGS = 9; 
    37     else static if(!is(T8 == void)) 
    38         const uint ARGS = 8; 
    39     else static if(!is(T7 == void)) 
    40         const uint ARGS = 7; 
    41     else static if(!is(T6 == void)) 
    42         const uint ARGS = 6; 
    43     else static if(!is(T5 == void)) 
    44         const uint ARGS = 5; 
    45     else static if(!is(T4 == void)) 
    46         const uint ARGS = 4; 
    47     else static if(!is(T3 == void)) 
    48         const uint ARGS = 3; 
    49     else static if(!is(T2 == void)) 
    50         const uint ARGS = 2; 
    51     else static if(!is(T1 == void)) 
    52         const uint ARGS = 1; 
    53     else 
    54         const uint ARGS = 0; 
    55     alias T1 arg1; 
    56     alias T2 arg2; 
    57     alias T3 arg3; 
    58     alias T4 arg4; 
    59     alias T5 arg5; 
    60     alias T6 arg6; 
    61     alias T7 arg7; 
    62     alias T8 arg8; 
    63     alias T9 arg9; 
    64     alias T10 arg10; 
     29private import pyd.tuples; 
     30 
     31template outer(T) { 
     32    T call_ctor()() { 
     33        return new T(); 
     34    } 
     35     
     36    T call_ctor(T1)(T1 t1) { 
     37        return new T(t1); 
     38    } 
     39     
     40    T call_ctor(T1, T2)(T1 t1, T2 t2) { 
     41        return new T(t1, t2); 
     42    } 
     43     
     44    T call_ctor(T1, T2, T3)(T1 t1, T2 t2, T3 t3) { 
     45        return new T(t1, t2, t3); 
     46    } 
     47     
     48    T call_ctor(T1, T2, T3, T4)(T1 t1, T2 t2, T3 t3, T4 t4) { 
     49        return new T(t1, t2, t3, t4); 
     50    } 
     51     
     52    T call_ctor(T1, T2, T3, T4, T5)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { 
     53        return new T(t1, t2, t3, t4, t5); 
     54    } 
     55     
     56    T call_ctor(T1, T2, T3, T4, T5, T6)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { 
     57        return new T(t1, t2, t3, t4, t5, t6); 
     58    } 
     59     
     60    T call_ctor(T1, T2, T3, T4, T5, T6, T7)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) { 
     61        return new T(t1, t2, t3, t4, t5, t6, t7); 
     62    } 
     63     
     64    T call_ctor(T1, T2, T3, T4, T5, T6, T7, T8)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) { 
     65        return new T(t1, t2, t3, t4, t5, t6, t7, t8); 
     66    } 
     67     
     68    T call_ctor(T1, T2, T3, T4, T5, T6, T7, T8, T9)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9) { 
     69        return new T(t1, t2, t3, t4, t5, t6, t7, t8, t9); 
     70    } 
     71     
     72    T call_ctor(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10) { 
     73        return new T(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10); 
     74    } 
    6575} 
    6676 
    67 struct dummy { } 
    68 alias ctor!(dummy) undefined; 
    69  
    70 // This template wraps an individual call to a constructor 
    71 template wrapped_ctor(T, alias Ctor) { 
    72     int wrapped_ctor(PyObject* self, PyObject* args, PyObject* kwds) { 
     77// This template accepts a list of "ctor" templates and uses them to wrap a Python tp_init function. 
     78template wrapped_ctors(T, Tuple) { 
     79    alias wrapped_class_object!(T) wrap_object; 
     80    const uint ARGS = Tuple.length; 
     81    extern(C) 
     82    int init_func(PyObject* self, PyObject* args, PyObject* kwds) { 
     83        int len = PyObject_Length(args); 
     84 
     85        try { 
     86 
    7387        T t; 
    74  
    75         try { /* begin try */ 
    76  
    77         static if (Ctor.ARGS == 1) { 
    78             t = new T( 
    79                 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)) 
    80             ); 
    81         } else static if (Ctor.ARGS == 2) { 
    82             t = new T( 
    83                 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 
    84                 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)) 
    85             ); 
    86         } else static if (Ctor.ARGS == 3) { 
    87             t = new T( 
    88                 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 
    89                 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 
    90                 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)) 
    91             ); 
    92         } else static if (Ctor.ARGS == 4) { 
    93             t = new T( 
    94                 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 
    95                 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 
    96                 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 
    97                 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)) 
    98             ); 
    99         } else static if (Ctor.ARGS == 5) { 
    100             t = new T( 
    101                 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 
    102                 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 
    103                 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 
    104                 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)), 
    105                 d_type!(Ctor.arg5)(PyTuple_GetItem(args, 4)) 
    106             ); 
    107         } else static if (Ctor.ARGS == 6) { 
    108             t = new T( 
    109                 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 
    110                 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 
    111                 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 
    112                 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)), 
    113                 d_type!(Ctor.arg5)(PyTuple_GetItem(args, 4)), 
    114                 d_type!(Ctor.arg6)(PyTuple_GetItem(args, 5)) 
    115             ); 
    116         } else static if (Ctor.ARGS == 7) { 
    117             t = new T( 
    118                 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 
    119                 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 
    120                 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 
    121                 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)), 
    122                 d_type!(Ctor.arg5)(PyTuple_GetItem(args, 4)), 
    123                 d_type!(Ctor.arg6)(PyTuple_GetItem(args, 5)), 
    124                 d_type!(Ctor.arg7)(PyTuple_GetItem(args, 6)) 
    125             ); 
    126         } else static if (Ctor.ARGS == 8) { 
    127             t = new T( 
    128                 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 
    129                 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 
    130                 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 
    131                 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)), 
    132                 d_type!(Ctor.arg5)(PyTuple_GetItem(args, 4)), 
    133                 d_type!(Ctor.arg6)(PyTuple_GetItem(args, 5)), 
    134                 d_type!(Ctor.arg7)(PyTuple_GetItem(args, 6)), 
    135                 d_type!(Ctor.arg8)(PyTuple_GetItem(args, 7)) 
    136             ); 
    137         } else static if (Ctor.ARGS == 9) { 
    138             t = new T( 
    139                 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 
    140                 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 
    141                 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 
    142                 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)), 
    143                 d_type!(Ctor.arg5)(PyTuple_GetItem(args, 4)), 
    144                 d_type!(Ctor.arg6)(PyTuple_GetItem(args, 5)), 
    145                 d_type!(Ctor.arg7)(PyTuple_GetItem(args, 6)), 
    146                 d_type!(Ctor.arg8)(PyTuple_GetItem(args, 7)), 
    147                 d_type!(Ctor.arg9)(PyTuple_GetItem(args, 8)) 
    148             ); 
    149         } else static if (Ctor.ARGS == 10) { 
    150             t = new T( 
    151                 d_type!(Ctor.arg1)(PyTuple_GetItem(args, 0)), 
    152                 d_type!(Ctor.arg2)(PyTuple_GetItem(args, 1)), 
    153                 d_type!(Ctor.arg3)(PyTuple_GetItem(args, 2)), 
    154                 d_type!(Ctor.arg4)(PyTuple_GetItem(args, 3)), 
    155                 d_type!(Ctor.arg5)(PyTuple_GetItem(args, 4)), 
    156                 d_type!(Ctor.arg6)(PyTuple_GetItem(args, 5)), 
    157                 d_type!(Ctor.arg7)(PyTuple_GetItem(args, 6)), 
    158                 d_type!(Ctor.arg8)(PyTuple_GetItem(args, 7)), 
    159                 d_type!(Ctor.arg9)(PyTuple_GetItem(args, 8)), 
    160                 d_type!(Ctor.arg10)(PyTuple_GetItem(args, 9)) 
    161             ); 
    162         } 
     88        // Default ctor 
     89        static if (is(typeof(new T))) { 
     90            if (len == 0) { 
     91                t = new T; 
     92                goto Done; 
     93            } 
     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; 
     114            } 
     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; 
     121            } 
     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; 
     128            } 
     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; 
     135            } 
     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; 
     142            } 
     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; 
     149            } 
     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; 
     156            } 
     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; 
     163            } 
     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; 
     170            } 
     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; 
     177            } 
     178        } else { 
     179            PyErr_SetString(PyExc_TypeError, "Unsupported number of constructor arguments."); 
     180            return -1; 
     181        } 
     182Done: 
     183        (cast(wrapped_class_object!(T)*)self).d_obj = t; 
     184        wrap_class_instances!(T)[t]++; 
    163185 
    164186        } /* end try */ 
     
    177199        } 
    178200 
    179         (cast(wrapped_class_object!(T)*)self).d_obj = t; 
    180         wrap_class_instances!(T)[t] = 1; 
    181  
    182201        return 0; 
    183202    } 
    184203} 
    185204 
    186 // This template accepts a list of "ctor" templates and uses them to wrap a Python __init__ function. 
    187 template wrapped_ctors(T, alias C1, alias C2, alias C3, alias C4, alias C5, alias C6, alias C7, alias C8, alias C9, alias C10) { 
    188     alias wrapped_class_object!(T) wrap_object; 
    189     static if (!is(C10.arg1 == dummy)) 
    190         const uint ARGS = 10; 
    191     else static if(!is(C9.arg1 == dummy)) 
    192         const uint ARGS = 9; 
    193     else static if(!is(C8.arg1 == dummy)) 
    194         const uint ARGS = 8; 
    195     else static if(!is(C7.arg1 == dummy)) 
    196         const uint ARGS = 7; 
    197     else static if(!is(C6.arg1 == dummy)) 
    198         const uint ARGS = 6; 
    199     else static if(!is(C5.arg1 == dummy)) 
    200         const uint ARGS = 5; 
    201     else static if(!is(C4.arg1 == dummy)) 
    202         const uint ARGS = 4; 
    203     else static if(!is(C3.arg1 == dummy)) 
    204         const uint ARGS = 3; 
    205     else static if(!is(C2.arg1 == dummy)) 
    206         const uint ARGS = 2; 
    207     else static if(!is(C1.arg1 == dummy)) 
    208         const uint ARGS = 1; 
    209     else 
    210         const uint ARGS = 0; 
    211     extern(C) 
    212     int init_func(PyObject* self, PyObject* args, PyObject* kwds) { 
    213         int len = PyObject_Length(args); 
    214         // Default ctor 
    215         static if (is(typeof(new T))) { 
    216             if (len == 0) { 
    217                 T t = new T; 
    218                 (cast(wrap_object*)self).d_obj = t; 
    219                 wrap_class_instances!(T)[t] = 1; 
    220                 return 0; 
    221             } 
    222         } 
    223         // We only match the first supplied ctor with the proper number of 
    224         // arguments. (Eventually, we'll do some more sophisticated matching, 
    225         // but this will do for now.) 
    226         static if (ARGS >= 1) { 
    227             if (len == C1.ARGS) 
    228                 return wrapped_ctor!(T, C1)(self, args, kwds); 
    229         } 
    230         static if (ARGS >= 2) { 
    231             if (len == C2.ARGS) 
    232                 return wrapped_ctor!(T, C2)(self, args, kwds); 
    233         } 
    234         static if (ARGS >= 3) { 
    235             if (len == C3.ARGS) 
    236                 return wrapped_ctor!(T, C3)(self, args, kwds); 
    237         } 
    238         static if (ARGS >= 4) { 
    239             if (len == C4.ARGS) 
    240                 return wrapped_ctor!(T, C4)(self, args, kwds); 
    241         } 
    242         static if (ARGS >= 5) { 
    243             if (len == C5.ARGS) 
    244                 return wrapped_ctor!(T, C5)(self, args, kwds); 
    245         } 
    246         static if (ARGS >= 6) { 
    247             if (len == C6.ARGS) 
    248                 return wrapped_ctor!(T, C6)(self, args, kwds); 
    249         } 
    250         static if (ARGS >= 7) { 
    251             if (len == C7.ARGS) 
    252                 return wrapped_ctor!(T, C7)(self, args, kwds); 
    253         } 
    254         static if (ARGS >= 8) { 
    255             if (len == C8.ARGS) 
    256                 return wrapped_ctor!(T, C8)(self, args, kwds); 
    257         } 
    258         static if (ARGS >= 9) { 
    259             if (len == C9.ARGS) 
    260                 return wrapped_ctor!(T, C9)(self, args, kwds); 
    261         } 
    262         static if (ARGS >= 10) { 
    263             if (len == C10.ARGS) 
    264                 return wrapped_ctor!(T, C10)(self, args, kwds); 
    265         } 
    266         PyErr_SetString(PyExc_TypeError, "Unsupported number of constructor arguments."); 
    267         return -1; 
    268     } 
    269 } 
    270  
  • trunk/infrastructure/pyd/def.d

    r26 r28  
    7777 *It's greater than 10!) 
    7878 */ 
    79 template def(char[] name, alias fn, uint MIN_ARGS = MIN_ARGS!(fn), fn_t=typeof(&fn)) { 
     79template def(alias fn, char[] name, fn_t=typeof(&fn), uint MIN_ARGS = MIN_ARGS!(fn)) { 
     80    pragma(msg, "def: " ~ name); 
    8081    void def() { 
    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); 
     82        PyMethodDef empty; 
     83        alias module_global_methods list; 
     84 
     85        list[length-1].ml_name = name ~ \0; 
     86        list[length-1].ml_meth = &func_wrap!(fn, MIN_ARGS, void, fn_t).func; 
     87        list[length-1].ml_flags = METH_VARARGS; 
     88        list[length-1].ml_doc = ""; 
     89        list ~= empty; 
    8590    } 
    8691} 
  • trunk/infrastructure/pyd/ftype.d

    r26 r28  
    149149{ 
    150150    private Tf fptr; 
     151    //pragma(msg, Tf); 
    151152    static if( is( typeof(*Tf) U == function ) ) 
    152153        alias U type; 
     
    599600/** 
    600601 * 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. 
     602 * function can accept. Note that this accepts an alias parameter rather than a 
     603 * function pointer type, as the function and delegate types contain no 
     604 * information about default arguments. 
     605 * 
     606 * (Written by Kirk McDonald.) 
    604607 */ 
    605608public 
  • trunk/infrastructure/pyd/func_wrap.d

    r27 r28  
    2929private import pyd.ftype; 
    3030private import pyd.make_object; 
     31private import pyd.tuples; 
    3132 
    3233private import std.string; 
    3334 
    3435// Builds a Python callable object from a delegate or function pointer. 
    35 template DPyFunc_FromDG(T, uint MIN_ARGS=NumberOfArgs!(T), C=void) { 
     36template DPyFunc_FromDG(T, uint MIN_ARGS=NumberOfArgs!(T)) { 
    3637    PyObject* DPyFunc_FromDG(T dg) { 
    3738        alias wrapped_class_type!(T) type; 
     
    4142            type.tp_basicsize = obj.sizeof; 
    4243            type.tp_name = "DPyFunc"; 
    43             type.tp_call = &wrapped_func_call!(T, MIN_ARGS, C).call; 
     44            type.tp_call = &wrapped_func_call!(T/*, MIN_ARGS*/).call; 
    4445            PyType_Ready(&type); 
    4546            is_wrapped!(T) = true; 
     
    5354} 
    5455 
    55 template wrapped_func_call(fn_t, uint MIN_ARGS, C=void) { 
     56// Calls the passed function with the passed Python tuple. 
     57ReturnType!(fn_t) py_call(fn_t, PY)(fn_t fn, PY* args) { 
     58    const uint MAX_ARGS = NumberOfArgs!(fn_t); 
     59    alias ReturnType!(fn_t) RetType; 
     60 
     61    int ARGS = 0; 
     62    // This can make it more convenient to call this with 0 args. 
     63    if (args !is null) { 
     64        ARGS = PyObject_Length(args); 
     65        assert(ARGS == MAX_ARGS, "Function called with wrong number of arguments"); 
     66    } 
     67 
     68    // Sanity check! 
     69    if (ARGS != MAX_ARGS) { 
     70        PyErr_SetString(PyExc_TypeError, 
     71            "Wrong number of arguments. Got " ~ 
     72            toString(ARGS) ~ 
     73            ", expected " ~ 
     74            toString(MAX_ARGS) ~ 
     75            " args."); 
     76        handle_exception(); 
     77    } 
     78 
     79    // I've refactored this to use a tuple rather than the old cascade of 
     80    // variable function calls. There are now 10 calls to d_type where there 
     81    // once were 110. 
     82    alias tuple_from_fn!(fn_t) t_t; // tuple type 
     83    t_t t; 
     84 
     85    static if (MAX_ARGS >= 1) 
     86        t.set!(0)(d_type!(t_t.TypeNo!(0))(PyTuple_GetItem(args, 0))); 
     87    static if (MAX_ARGS >= 2) 
     88        t.set!(1)(d_type!(t_t.TypeNo!(1))(PyTuple_GetItem(args, 1))); 
     89    static if (MAX_ARGS >= 3) 
     90        t.set!(2)(d_type!(t_t.TypeNo!(2))(PyTuple_GetItem(args, 2))); 
     91    static if (MAX_ARGS >= 4) 
     92        t.set!(3)(d_type!(t_t.TypeNo!(3))(PyTuple_GetItem(args, 3))); 
     93    static if (MAX_ARGS >= 5) 
     94        t.set!(4)(d_type!(t_t.TypeNo!(4))(PyTuple_GetItem(args, 4))); 
     95    static if (MAX_ARGS >= 6) 
     96        t.set!(5)(d_type!(t_t.TypeNo!(5))(PyTuple_GetItem(args, 5))); 
     97    static if (MAX_ARGS >= 7) 
     98        t.set!(6)(d_type!(t_t.TypeNo!(6))(PyTuple_GetItem(args, 6))); 
     99    static if (MAX_ARGS >= 8) 
     100        t.set!(7)(d_type!(t_t.TypeNo!(7))(PyTuple_GetItem(args, 7))); 
     101    static if (MAX_ARGS >= 9) 
     102        t.set!(8)(d_type!(t_t.TypeNo!(8))(PyTuple_GetItem(args, 8))); 
     103    static if (MAX_ARGS >= 10) 
     104        t.set!(9)(d_type!(t_t.TypeNo!(9))(PyTuple_GetItem(args, 9))); 
     105 
     106    static if (is(RetType : void)) { 
     107        apply_tuple_to_fn(t, fn); 
     108        return; 
     109    } else { 
     110        return apply_tuple_to_fn(t, fn); 
     111    } 
     112
     113 
     114template wrapped_func_call(fn_t/*, uint MIN_ARGS*/) { 
    56115    const uint MAX_ARGS = NumberOfArgs!(fn_t); 
    57116    alias ReturnType!(fn_t) RetType; 
     
    62121            return null; 
    63122        } 
    64         fn_t real_fn = (cast(wrapped_class_object!(fn_t)*)self).d_obj; 
     123 
     124        fn_t fn = (cast(wrapped_class_object!(fn_t)*)self).d_obj; 
    65125        PyObject* ret; 
    66126 
    67         // If C is specified, then this is a method call. We need to pull out 
    68         // the "self" object that is the first item in args and turn the member 
    69         // function pointer in real_fn into a delegate. This conversion is done 
    70         // with a dirty hack; see dg_convert.d. 
    71         static if (!is(C == void)) { 
    72             C instance = (cast(wrapped_class_object!(C)*)PyTuple_GetItem(args, 0)).d_obj; 
    73             fn_to_dg!(fn_t) fn = dg_wrapper!(C, fn_t)(instance, real_fn); 
    74             // Pull out the first argument. 
    75             args = PyTuple_GetSlice(args, 1, PyTuple_Size(args)); 
    76             scope(exit) Py_DECREF(args); 
    77         // If C is not specified, then this is just a normal function call. 
    78         } else { 
    79             fn_t fn = real_fn; 
    80         } 
    81  
    82         // Sanity check! 
    83         int ARGS = 0; 
    84         // This can make it more convenient to call this with 0 args. 
    85         if (args !is null) 
    86             ARGS = PyObject_Length(args); 
    87         if (ARGS < MIN_ARGS || ARGS > MAX_ARGS) { 
    88             PyErr_SetString(PyExc_TypeError, 
    89                 "Wrong number of arguments. Got " ~ 
    90                 toString(ARGS) ~ 
    91                 ", expected between " ~ 
    92                 toString(MIN_ARGS) ~ "-" ~ toString(MAX_ARGS) ~ 
    93                 " args."); 
    94             return null; 
    95         } 
    96  
    97         try { /* begin try */ 
    98  
    99         static if (MIN_ARGS <= 0 && MAX_ARGS >= 0) { 
    100             if (ARGS == 0) { 
    101                 // If the return type is void... 
    102                 static if (is(RetType : void)) { 
    103                     fn(); 
    104                     // Return Py_None 
    105                     Py_INCREF(Py_None); 
    106                     ret = Py_None; 
    107                 } else { 
    108                     // Otherwise, return a conversion of the return value 
    109                     ret = _py( fn() ); 
    110                 } 
     127        try { 
     128            static if (is(RetType == void)) { 
     129                py_call/+!(fn_t/*, MIN_ARGS*/)+/(fn, args); 
     130                Py_INCREF(Py_None); 
     131                ret = Py_None; 
     132            } else { 
     133                ret = _py( py_call/+!(fn_t/*, MIN_ARGS*/)+/(fn, args) ); 
    111134            } 
    112         } static if (MIN_ARGS <= 1 && MAX_ARGS >= 1) { 
    113             if (ARGS == 1) { 
    114                 // See, this ugly code works like this: 
    115                 // (1) _py takes the return type of the wrapped function, and 
    116                 // converts it to a PyObject*, which is passed straight back into 
    117                 // Python. 
    118                 // (2) fn is the wrapped function. Each of its arguments take the 
    119                 // form: 
    120                 // (3) d_type is a template function. It converts a PyObject* into 
    121                 // a reasonable D type. The template argument is the type to 
    122                 // convert to. The function argument is the PyObject* to convert. 
    123                 // (4) ArgType derives the type of an argument to the function. It 
    124                 // (therefore) is used to pass the correct type into d_type's 
    125                 // template argument. 
    126                 // This pattern is repeated umpteen times, as each number of 
    127                 // function arguments requires its own statement TWICE, as void 
    128                 // return types must be handled differently. 
    129                 static if (is(RetType : void)) { 
    130                     // Call with void return type 
    131                     fn( 
    132                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)) 
    133                     ); 
    134                     // Return Py_None 
    135                     Py_INCREF(Py_None); 
    136                     ret = Py_None; 
    137                 } else { 
    138                     // Capture return value 
    139                     ret = _py( fn( 
    140                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)) 
    141                     ) ); 
    142                 } 
    143             } 
    144         } static if (MIN_ARGS <= 2 && MAX_ARGS >= 2) { 
    145             if (ARGS == 2) { 
    146                 static if (is(RetType : void)) { 
    147                     fn( 
    148                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 
    149                         d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)) 
    150                     ); 
    151                     Py_INCREF(Py_None); 
    152                     ret = Py_None; 
    153                 } else { 
    154                     ret = _py( fn( 
    155                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 
    156                         d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)) 
    157                     ) ); 
    158                 } 
    159             } 
    160         } static if (MIN_ARGS <= 3 && MAX_ARGS >= 3) { 
    161             if (ARGS == 3) { 
    162                 static if (is(RetType : void)) { 
    163                     fn( 
    164                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 
    165                         d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 
    166                         d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)) 
    167                     ); 
    168                     Py_INCREF(Py_None); 
    169                     ret = Py_None; 
    170                 } else { 
    171                     ret = _py( fn( 
    172                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 
    173                         d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 
    174                         d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)) 
    175                     ) ); 
    176                 } 
    177             } 
    178         } static if (MIN_ARGS <= 4 && MAX_ARGS >= 4) { 
    179             if (ARGS == 4) { 
    180                 static if (is(RetType : void)) { 
    181                     fn( 
    182                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 
    183                         d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 
    184                         d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 
    185                         d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)) 
    186                     ); 
    187                     Py_INCREF(Py_None); 
    188                     ret = Py_None; 
    189                 } else { 
    190                     ret = _py( fn( 
    191                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 
    192                         d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 
    193                         d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 
    194                         d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)) 
    195                     ) ); 
    196                 } 
    197             } 
    198         } static if (MIN_ARGS <= 5 && MAX_ARGS >= 5) { 
    199             if (ARGS == 5) { 
    200                 static if (is(RetType : void)) { 
    201                     fn( 
    202                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 
    203                         d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 
    204                         d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 
    205                         d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 
    206                         d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)) 
    207                     ); 
    208                     Py_INCREF(Py_None); 
    209                     ret = Py_None; 
    210                 } else { 
    211                     ret = _py( fn( 
    212                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 
    213                         d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 
    214                         d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 
    215                         d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 
    216                         d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)) 
    217                     ) ); 
    218                 } 
    219             } 
    220         } static if (MIN_ARGS <= 6 && MAX_ARGS >= 6) { 
    221             if (ARGS == 6) { 
    222                 static if (is(RetType : void)) { 
    223                     fn( 
    224                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 
    225                         d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 
    226                         d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 
    227                         d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 
    228                         d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)), 
    229                         d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)) 
    230                     ); 
    231                     Py_INCREF(Py_None); 
    232                     ret = Py_None; 
    233                 } else { 
    234                     ret = _py( fn( 
    235                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 
    236                         d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 
    237                         d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 
    238                         d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 
    239                         d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)), 
    240                         d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)) 
    241                     ) ); 
    242                 } 
    243             } 
    244         } static if (MIN_ARGS <= 7 && MAX_ARGS >= 7) { 
    245             if (ARGS == 7) { 
    246                 static if (is(RetType : void)) { 
    247                     fn( 
    248                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 
    249                         d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 
    250                         d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 
    251                         d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 
    252                         d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)), 
    253                         d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)), 
    254                         d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6)) 
    255                     ); 
    256                     Py_INCREF(Py_None); 
    257                     ret = Py_None; 
    258                 } else { 
    259                     ret = _py( fn( 
    260                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 
    261                         d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 
    262                         d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 
    263                         d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 
    264                         d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)), 
    265                         d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)), 
    266                         d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6)) 
    267                     ) ); 
    268                 } 
    269             } 
    270         } static if (MIN_ARGS <= 8 && MAX_ARGS >= 8) { 
    271             if (ARGS == 8) { 
    272                 static if (is(RetType : void)) { 
    273                     fn( 
    274                         d_type!(ArgType!(fn_t, 1))(PyTuple_GetItem(args, 0)), 
    275                         d_type!(ArgType!(fn_t, 2))(PyTuple_GetItem(args, 1)), 
    276                         d_type!(ArgType!(fn_t, 3))(PyTuple_GetItem(args, 2)), 
    277                         d_type!(ArgType!(fn_t, 4))(PyTuple_GetItem(args, 3)), 
    278                         d_type!(ArgType!(fn_t, 5))(PyTuple_GetItem(args, 4)), 
    279                         d_type!(ArgType!(fn_t, 6))(PyTuple_GetItem(args, 5)), 
    280                         d_type!(ArgType!(fn_t, 7))(PyTuple_GetItem(args, 6)), 
    281                         d_type!(ArgType!(fn_t, 8))(PyTuple_GetItem(args, 7)) 
    282                     ); 
    283