From 692123408b4acf2ede5c809828ce625013477cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ullrich=20K=C3=B6the?= Date: Fri, 10 Nov 2000 15:54:08 +0000 Subject: [PATCH] generalized the new def_raw() feature [SVN r8168] --- class_wrapper.h | 5 ++++- extclass.h | 7 +++++-- extclass_demo.cpp | 44 +++++++++++++++++++++++++++++--------------- functions.h | 27 +++++++++++++++++++-------- gen_extclass.py | 7 +++++-- module.cpp | 5 ----- module.h | 6 +++++- pyptr.h | 4 ++-- test_extclass.py | 19 +++++++++++++++++++ 9 files changed, 88 insertions(+), 36 deletions(-) diff --git a/class_wrapper.h b/class_wrapper.h index ac2e208e..34b849f6 100644 --- a/class_wrapper.h +++ b/class_wrapper.h @@ -30,7 +30,10 @@ class ClassWrapper // to C++ verbatim (as a 'Tuple const &' and 'Dict const &' // respectively). This is useful for manual argument passing. // It's also the only possibility to pass keyword arguments to C++. - void def_raw(RawArgumentsFunction::PtrFun fn, const char* name) + // Fn must have a signatur that is compatible to + // PyObject * (*)(PyObject * aTuple, PyObject * aDictionary) + template + void def_raw(Fn fn, const char* name) { m_class->def_raw(fn, name); } // define member functions. In fact this works for free functions, too - diff --git a/extclass.h b/extclass.h index f338f29d..8e3ec293 100644 --- a/extclass.h +++ b/extclass.h @@ -374,9 +374,12 @@ class ExtensionClass // to C++ verbatim (as a 'Tuple const &' and 'Dict const &' // respectively). This is useful for manual argument passing. // It's also the only possibility to pass keyword arguments to C++. - void def_raw(RawArgumentsFunction::PtrFun fn, const char* name) + // Fn must have a signatur that is compatible to + // PyObject * (*)(PyObject * aTuple, PyObject * aDictionary) + template + void def_raw(Fn fn, const char* name) { - this->add_method(new RawArgumentsFunction(fn), name); + this->add_method(py::detail::new_raw_arguments_function(fn), name); } // define member functions. In fact this works for free functions, too - diff --git a/extclass_demo.cpp b/extclass_demo.cpp index a67688d3..d719d3e1 100644 --- a/extclass_demo.cpp +++ b/extclass_demo.cpp @@ -563,25 +563,20 @@ struct RawTest int i_; }; -template class py::ExtensionClass; +PyObject * raw(py::Tuple const & args, py::Dict const & keywords); -PyObject * raw(py::Tuple const & args, py::Dict const & keywords) +int raw1(PyObject * args, PyObject * keywords) { - if(args.size() != 2 || keywords.size() != 2) - { - PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); - throw py::ArgumentError(); - } - - RawTest * first = from_python(args[0].get(), py::Type()); - int second = from_python(args[1].get(), py::Type()); - - int third = from_python(keywords[py::String("third")].get(), py::Type()); - int fourth = from_python(keywords[py::String("fourth")].get(), py::Type()); - - return to_python(first->i_ + second + third + fourth); + return PyTuple_Size(args) + PyDict_Size(keywords); } +int raw2(py::Ptr args, py::Ptr keywords) +{ + return PyTuple_Size(args.get()) + PyDict_Size(keywords.get()); +} + + + /************************************************************/ /* */ /* Ratio */ @@ -853,6 +848,25 @@ void init_module(py::Module& m) rawtest_class.def_raw(&raw, "raw"); m.def_raw(&raw, "raw"); + m.def_raw(&raw1, "raw1"); + m.def_raw(&raw2, "raw2"); +} + +PyObject * raw(py::Tuple const & args, py::Dict const & keywords) +{ + if(args.size() != 2 || keywords.size() != 2) + { + PyErr_SetString(PyExc_TypeError, "wrong number of arguments"); + throw py::ArgumentError(); + } + + RawTest * first = from_python(args[0].get(), py::Type()); + int second = from_python(args[1].get(), py::Type()); + + int third = from_python(keywords[py::String("third")].get(), py::Type()); + int fourth = from_python(keywords[py::String("fourth")].get(), py::Type()); + + return to_python(first->i_ + second + third + fourth); } void init_module() diff --git a/functions.h b/functions.h index eba23f89..dac7ba4f 100644 --- a/functions.h +++ b/functions.h @@ -75,24 +75,28 @@ struct WrappedFunctionPointer : Function const PtrFun m_pf; }; -// RawArgumentsFunction +// raw_arguments_function // A function that passes the Python argument tuple and keyword dictionary // verbatim to C++ (useful for customized argument parsing and variable // argument lists) -struct RawArgumentsFunction : Function +template +struct raw_arguments_function : Function { - typedef PyObject * (*PtrFun)(Tuple const &, Dict const &); + typedef Ret (*PtrFun)(Args, Keywords); - RawArgumentsFunction(PtrFun pf) + raw_arguments_function(PtrFun pf) : m_pf(pf) {} private: PyObject* do_call(PyObject* args, PyObject* keywords) const { - return (*m_pf)(Tuple(Ptr(args, Ptr::new_ref)), - keywords ? - Dict(Ptr(keywords, Ptr::new_ref)) : - Dict()); + Ptr dict(keywords ? + Ptr(keywords, Ptr::new_ref) : + PyDict_New()); + + return to_python( + (*m_pf)(from_python(args, py::Type()), + from_python(dict.get(), py::Type()))); } const char* description() const @@ -155,6 +159,13 @@ inline Function* new_wrapped_function(F pmf) } namespace detail { + template + Function* new_raw_arguments_function(R (*pmf)(Args, Keywords)) + { + return new raw_arguments_function(pmf); + } + + // A helper function for new_virtual_function(), below. Implements the core // functionality once the return type has already been deduced. R is expected to // be Type, where X is the actual return type of V. diff --git a/gen_extclass.py b/gen_extclass.py index 64363ce9..f4a87c58 100644 --- a/gen_extclass.py +++ b/gen_extclass.py @@ -379,9 +379,12 @@ class ExtensionClass // to C++ verbatim (as a 'Tuple const &' and 'Dict const &' // respectively). This is useful for manual argument passing. // It's also the only possibility to pass keyword arguments to C++. - void def_raw(RawArgumentsFunction::PtrFun fn, const char* name) + // Fn must have a signatur that is compatible to + // PyObject * (*)(PyObject * aTuple, PyObject * aDictionary) + template + void def_raw(Fn fn, const char* name) { - this->add_method(new RawArgumentsFunction(fn), name); + this->add_method(py::detail::new_raw_arguments_function(fn), name); } // define member functions. In fact this works for free functions, too - diff --git a/module.cpp b/module.cpp index 6bd4d07e..f4e9f91f 100644 --- a/module.cpp +++ b/module.cpp @@ -34,11 +34,6 @@ void Module::add(PyTypeObject* x, const char* name /*= 0*/) name ? name : x->tp_name); } -void Module::def_raw(RawFunctionPtr fn, const char* name) -{ - add(new RawArgumentsFunction(fn), name); -} - PyMethodDef Module::initial_methods[] = { { 0, 0, 0, 0 } }; } diff --git a/module.h b/module.h index 0215622a..268bd15b 100644 --- a/module.h +++ b/module.h @@ -30,7 +30,11 @@ public: void add(Ptr x, const char*name); - void def_raw(RawFunctionPtr fn, const char* name); + template + void def_raw(Fn fn, const char* name) + { + add(py::detail::new_raw_arguments_function(fn), name); + } template void def(Fn fn, const char* name) diff --git a/pyptr.h b/pyptr.h index dbdbcbf6..35de846f 100644 --- a/pyptr.h +++ b/pyptr.h @@ -28,10 +28,10 @@ template struct PyPtrConversions : Base { inline friend T from_python(PyObject* x, py::Type) - { return T(py::Downcast(x).get(), T::new_ref); } + { return T(py::Downcast(x).get(), T::new_ref); } inline friend T from_python(PyObject* x, py::Type) - { return T(py::Downcast(x).get(), T::new_ref); } + { return T(py::Downcast(x).get(), T::new_ref); } inline friend PyObject* to_python(T x) { return py::as_object(x.release()); } diff --git a/test_extclass.py b/test_extclass.py index 4a274acf..640bef8f 100644 --- a/test_extclass.py +++ b/test_extclass.py @@ -858,6 +858,25 @@ test inheritB2 >>> raw(r,1) Traceback (innermost last): TypeError: wrong number of arguments + >>> raw() + Traceback (innermost last): + TypeError: wrong number of arguments + >>> raw1(1,second=1) + 2 + >>> raw1(1) + 1 + >>> raw1(second=1) + 1 + >>> raw1() + 0 + >>> raw2(1,second=1) + 2 + >>> raw2(1) + 1 + >>> raw2(second=1) + 1 + >>> raw2() + 0 ========= Prove that the "phantom base class" issue is resolved ==========