2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-21 17:12:22 +00:00

generalized the new def_raw() feature

[SVN r8168]
This commit is contained in:
Ullrich Köthe
2000-11-10 15:54:08 +00:00
parent aed148838f
commit 692123408b
9 changed files with 88 additions and 36 deletions

View File

@@ -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 <class Fn>
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 -

View File

@@ -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 <class Fn>
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 -

View File

@@ -563,25 +563,20 @@ struct RawTest
int i_;
};
template class py::ExtensionClass<RawTest>;
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<RawTest *>());
int second = from_python(args[1].get(), py::Type<int>());
int third = from_python(keywords[py::String("third")].get(), py::Type<int>());
int fourth = from_python(keywords[py::String("fourth")].get(), py::Type<int>());
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<RawTest *>());
int second = from_python(args[1].get(), py::Type<int>());
int third = from_python(keywords[py::String("third")].get(), py::Type<int>());
int fourth = from_python(keywords[py::String("fourth")].get(), py::Type<int>());
return to_python(first->i_ + second + third + fourth);
}
void init_module()

View File

@@ -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 <class Ret, class Args, class Keywords>
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<Args>()),
from_python(dict.get(), py::Type<Keywords>())));
}
const char* description() const
@@ -155,6 +159,13 @@ inline Function* new_wrapped_function(F pmf)
}
namespace detail {
template <class R, class Args, class Keywords>
Function* new_raw_arguments_function(R (*pmf)(Args, Keywords))
{
return new raw_arguments_function<R, Args, Keywords>(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<X>, where X is the actual return type of V.

View File

@@ -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 <class Fn>
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 -

View File

@@ -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 } };
}

View File

@@ -30,7 +30,11 @@ public:
void add(Ptr x, const char*name);
void def_raw(RawFunctionPtr fn, const char* name);
template <class Fn>
void def_raw(Fn fn, const char* name)
{
add(py::detail::new_raw_arguments_function(fn), name);
}
template <class Fn>
void def(Fn fn, const char* name)

View File

@@ -28,10 +28,10 @@ template <class T, class Base>
struct PyPtrConversions : Base
{
inline friend T from_python(PyObject* x, py::Type<const T&>)
{ return T(py::Downcast<T::value_type>(x).get(), T::new_ref); }
{ return T(py::Downcast<typename T::value_type>(x).get(), T::new_ref); }
inline friend T from_python(PyObject* x, py::Type<T>)
{ return T(py::Downcast<T::value_type>(x).get(), T::new_ref); }
{ return T(py::Downcast<typename T::value_type>(x).get(), T::new_ref); }
inline friend PyObject* to_python(T x)
{ return py::as_object(x.release()); }

View File

@@ -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 ==========