Changeset 27

Show
Ignore:
Timestamp:
07/06/06 03:38:28 (2 years ago)
Author:
KirkMcDonald
Message:

PyCallable? to delegate conversion.

Files:

Legend:

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

    r26 r27  
    6464} 
    6565 
     66void dg_test(void delegate() dg) { 
     67    dg(); 
     68} 
     69 
    6670class Bar { 
    6771    int[] m_a; 
     
    98102    def!("iter_test", iter_test); 
    99103    def!("func_test", func_test); 
     104    def!("dg_test", dg_test); 
    100105 
    101106    wrapped_class!("Foo", Foo) f; 
  • trunk/infrastructure/pyd/class_wrap.d

    r26 r27  
    3333private import std.string; 
    3434 
     35bool[TypeInfo] wrapped_classes; 
     36 
     37// This is split out in case I ever want to make a subtype of a wrapped class. 
    3538template DPyObject_HEAD(T) { 
    3639    mixin PyObject_HEAD; 
     
    346349    PyModule_AddObject(DPy_Module_p, name, cast(PyObject*)&type); 
    347350    is_wrapped!(T) = true; 
    348 
     351    wrapped_classes[typeid(T)] = true; 
     352
  • trunk/infrastructure/pyd/func_wrap.d

    r26 r27  
    4444            PyType_Ready(&type); 
    4545            is_wrapped!(T) = true; 
     46            wrapped_classes[typeid(T)] = true; 
    4647        } 
    4748        obj* func = cast(obj*)type.tp_new(&type, null, null); 
     
    412413} 
    413414 
     415//----------------------------------------------------------------------------- 
     416// And now the reverse operation: wrapping a Python callable with a delegate. 
     417// These rely on a whole collection of nasty templates, but the result is both 
     418// flexible and pretty fast. 
     419// (Sadly, wrapping a Python callable with a regular function is not quite 
     420// possible.) 
     421//----------------------------------------------------------------------------- 
     422// The steps involved when calling this function are as follows: 
     423// 1) An instance of DPyWrappedFunc is made, and the callable placed within. 
     424// 2) The delegate type Dg is broken into its constituent parts. 
     425// 3) These parts are used to get the proper overload of DPyWrappedFunc.fn 
     426// 4) A delegate to DPyWrappedFunc.fn is returned. 
     427// 5) When fn is called, it attempts to cram the arguments into the callable. 
     428//    If Python objects to this, an exception is raised. Note that this means 
     429//    any error in converting the callable to a given delegate can only be 
     430//    detected at runtime. 
     431 
     432Dg DPyCallable_AsDelegate(Dg) (PyObject* c) { 
     433    auto f = new DPyWrappedFunc(c); 
     434 
     435    const uint ARGS = NumberOfArgs!(Dg); 
     436    alias ReturnType!(Dg) Tr; 
     437    static if (ARGS == 0) 
     438        return &f.fn!(Tr); 
     439    else static if (ARGS == 1) 
     440        return &f.fn!(Tr, ArgType!(Dg, 1)); 
     441    else static if (ARGS == 2) 
     442        return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2)); 
     443    else static if (ARGS == 3) 
     444        return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3)); 
     445    else static if (ARGS == 4) 
     446        return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4)); 
     447    else static if (ARGS == 5) 
     448        return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4), ArgType!(Dg, 5)); 
     449    else static if (ARGS == 6) 
     450        return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4), ArgType!(Dg, 5), ArgType!(Dg, 6)); 
     451    else static if (ARGS == 7) 
     452        return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4), ArgType!(Dg, 5), ArgType!(Dg, 6), ArgType!(Dg, 7)); 
     453    else static if (ARGS == 8) 
     454        return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4), ArgType!(Dg, 5), ArgType!(Dg, 6), ArgType!(Dg, 7), ArgType!(Dg, 8)); 
     455    else static if (ARGS == 9) 
     456        return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4), ArgType!(Dg, 5), ArgType!(Dg, 6), ArgType!(Dg, 7), ArgType!(Dg, 8), ArgType!(Dg, 9)); 
     457    else static if (ARGS == 10) 
     458        return &f.fn!(Tr, ArgType!(Dg, 1), ArgType!(Dg, 2), ArgType!(Dg, 3), ArgType!(Dg, 4), ArgType!(Dg, 5), ArgType!(Dg, 6), ArgType!(Dg, 7), ArgType!(Dg, 8), ArgType!(Dg, 9), ArgType!(Dg, 10)); 
     459    else static assert(false, "Unsupported number of args in delegate type."); 
     460} 
     461 
     462class Dummy { } 
     463 
     464private 
     465class DPyWrappedFunc { 
     466    PyObject* callable; 
     467 
     468    this(PyObject* c) { callable = c; Py_INCREF(c); } 
     469    ~this() { Py_DECREF(callable); } 
     470     
     471    Tr boilerplate(Tr)(PyObject* ret) { 
     472        if (ret is null) handle_exception(); 
     473        scope(exit) Py_DECREF(ret); 
     474        return d_type!(Tr)(ret); 
     475    } 
     476     
     477    Tr fn(Tr)() { 
     478        return boilerplate!(Tr)(call()); 
     479    } 
     480     
     481    Tr fn(Tr, T1)(T1 t1) { 
     482        return boilerplate!(Tr)(call(t1)); 
     483    } 
     484 
     485    Tr fn(Tr, T1, T2)(T1 t1, T2 t2) { 
     486        return boilerplate!(Tr)(call(t1, t2)); 
     487    } 
     488 
     489    Tr fn(Tr, T1, T2, T3)(T1 t1, T2 t2, T3 t3) { 
     490        return boilerplate!(Tr)(call(t1, t2, t3)); 
     491    } 
     492 
     493    Tr fn(Tr, T1, T2, T3, T4)(T1 t1, T2 t2, T3 t3, T4 t4) { 
     494        return boilerplate!(Tr)(call(t1, t2, t3, t4)); 
     495    } 
     496 
     497    Tr fn(Tr, T1, T2, T3, T4, T5)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { 
     498        return boilerplate!(Tr)(call(t1, t2, t3, t4, t5)); 
     499    } 
     500 
     501    Tr fn(Tr, T1, T2, T3, T4, T5, T6)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { 
     502        return boilerplate!(Tr)(call(t1, t2, t3, t4, t5, t6)); 
     503    } 
     504 
     505    Tr fn(Tr, T1, T2, T3, T4, T5, T6, T7)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) { 
     506        return boilerplate!(Tr)(call(t1, t2, t3, t4, t5, t6, t7)); 
     507    } 
     508 
     509    Tr fn(Tr, T1, T2, T3, T4, T5, T6, T7, T8)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) { 
     510        return boilerplate!(Tr)(call(t1, t2, t3, t4, t5, t6, t7, t8)); 
     511    } 
     512 
     513    Tr fn(Tr, 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) { 
     514        return boilerplate!(Tr)(call(t1, t2, t3, t4, t5, t6, t7, t8, t9)); 
     515    } 
     516 
     517    Tr fn(Tr, 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) { 
     518        return boilerplate!(Tr)(call(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); 
     519    } 
     520     
     521    template call(T1=Dummy, T2=Dummy, T3=Dummy, T4=Dummy, T5=Dummy, T6=Dummy, T7=Dummy, T8=Dummy, T9=Dummy, T10=Dummy) { 
     522        PyObject* call (T1 t1=null, T2 t2=null, T3 t3=null, T4 t4=null, T5 t5=null, T6 t6=null, T7 t7=null, T8 t8=null, T9 t9=null, T10 t10=null) { 
     523            static if (!is(T10 == Dummy)) 
     524                const uint ARGS = 10; 
     525            else static if (!is(T9 == Dummy)) 
     526                const uint ARGS = 9; 
     527            else static if (!is(T8 == Dummy)) 
     528                const uint ARGS = 8; 
     529            else static if (!is(T7 == Dummy)) 
     530                const uint ARGS = 7; 
     531            else static if (!is(T6 == Dummy)) 
     532                const uint ARGS = 6; 
     533            else static if (!is(T5 == Dummy)) 
     534                const uint ARGS = 5; 
     535            else static if (!is(T4 == Dummy)) 
     536                const uint ARGS = 4; 
     537            else static if (!is(T3 == Dummy)) 
     538                const uint ARGS = 3; 
     539            else static if (!is(T2 == Dummy)) 
     540                const uint ARGS = 2; 
     541            else static if (!is(T1 == Dummy)) 
     542                const uint ARGS = 1; 
     543            else 
     544                const uint ARGS = 0; 
     545            PyObject* t = PyTuple_New(ARGS); 
     546            if (t is null) return null; 
     547            scope(exit) Py_DECREF(t); 
     548            static if (!is(T10 == Dummy)) 
     549                PyTuple_SetItem(t, 9, _py(t10)); 
     550            static if (!is(T9 == Dummy)) 
     551                PyTuple_SetItem(t, 8, _py(t9)); 
     552            static if (!is(T8 == Dummy)) 
     553                PyTuple_SetItem(t, 7, _py(t8)); 
     554            static if (!is(T7 == Dummy)) 
     555                PyTuple_SetItem(t, 6, _py(t7)); 
     556            static if (!is(T6 == Dummy)) 
     557                PyTuple_SetItem(t, 5, _py(t6)); 
     558            static if (!is(T5 == Dummy)) 
     559                PyTuple_SetItem(t, 4, _py(t5)); 
     560            static if (!is(T4 == Dummy)) 
     561                PyTuple_SetItem(t, 3, _py(t4)); 
     562            static if (!is(T3 == Dummy)) 
     563                PyTuple_SetItem(t, 2, _py(t3)); 
     564            static if (!is(T2 == Dummy)) 
     565                PyTuple_SetItem(t, 1, _py(t2)); 
     566            static if (!is(T1 == Dummy)) 
     567                PyTuple_SetItem(t, 0, _py(t1)); 
     568            return PyObject_CallObject(callable, t); 
     569        } 
     570    } 
     571} 
  • trunk/infrastructure/pyd/make_object.d

    r26 r27  
    232232    } else static if (is(DPyObject : T)) { 
    233233        return new DPyObject(o); 
     234    } else static if (is(T == void)) { 
     235        if (o != Py_None) could_not_convert!(T)(o); 
     236        Py_INCREF(Py_None); 
     237        return Py_None; 
    234238    } else static if (is(T == class)) { 
    235239        // We can only convert to a class if it has been wrapped, and of course 
    236240        // we can only convert the object if it is the wrapped type. 
    237241        if (is_wrapped!(T) && PyObject_TypeCheck(o, &wrapped_class_type!(T))) { 
    238                 return (cast(wrapped_class_object!(T)*)o).d_obj; 
     242            return (cast(wrapped_class_object!(T)*)o).d_obj; 
    239243        } 
    240244        // Otherwise, throw up an exception. 
    241245        could_not_convert!(T)(o); 
     246    } else static if (is(T == delegate)) { 
     247        if (PyCallable_Check(o)) { 
     248            return DPyCallable_AsDelegate!(T)(o); 
     249        } else could_not_convert!(T)(o); 
    242250    /+ 
    243251    } else static if (is(wchar[] : T)) {