2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-24 18:12:43 +00:00

More converter centralization

[SVN r14487]
This commit is contained in:
Dave Abrahams
2002-07-17 01:54:58 +00:00
parent 134bc44c45
commit 244e0fa5e6
13 changed files with 369 additions and 240 deletions

View File

@@ -0,0 +1,35 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef ALWAYS_EXTRACT_OBJECT_MANAGER_DWA2002716_HPP
# define ALWAYS_EXTRACT_OBJECT_MANAGER_DWA2002716_HPP
# include <boost/config.hpp>
namespace boost { namespace python { namespace converter {
// Derive specializations of extract_object_manager from this when the
// object manager is indiscriminate about the Python objects it manages
struct always_extract_object_manager
{
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
static inline bool check(PyObject* x);
};
// Provide a forward declaration as a convenience for clients, who all
// need it.
template <class T> struct extract_object_manager;
//
// implementations
//
inline bool always_extract_object_manager::check(PyObject* x)
{
return true;
}
}}} // namespace boost::python::converter
#endif // ALWAYS_EXTRACT_OBJECT_MANAGER_DWA2002716_HPP

View File

@@ -19,6 +19,7 @@
# include <boost/python/detail/void_ptr.hpp>
# include <boost/python/back_reference.hpp>
# include <boost/python/detail/referent_storage.hpp>
# include <boost/python/converter/obj_mgr_arg_from_python.hpp>
namespace boost { namespace python
{
@@ -139,6 +140,12 @@ struct back_reference_arg_from_python
template <class T>
struct select_arg_from_python
{
BOOST_STATIC_CONSTANT(
bool, obj_mgr = is_object_manager<T>::value);
BOOST_STATIC_CONSTANT(
bool, obj_mgr_ref = is_reference_to_object_manager<T>::value);
BOOST_STATIC_CONSTANT(
bool, ptr = is_pointer<T>::value);
@@ -159,22 +166,30 @@ struct select_arg_from_python
boost::python::is_back_reference<T>::value);
typedef typename mpl::select_type<
ptr
, pointer_arg_from_python<T>
, typename mpl::select_type<
ptr_cref
, pointer_cref_arg_from_python<T>
, typename mpl::select_type<
ref
, reference_arg_from_python<T>
, typename mpl::select_type<
back_ref
, back_reference_arg_from_python<T>
, arg_rvalue_from_python<T>
>::type
>::type
obj_mgr
, object_manager_value_arg_from_python<T>
, mpl::select_type<
obj_mgr_ref
, object_manager_ref_arg_from_python<T>
, mpl::select_type<
ptr
, pointer_arg_from_python<T>
, typename mpl::select_type<
ptr_cref
, pointer_cref_arg_from_python<T>
, typename mpl::select_type<
ref
, reference_arg_from_python<T>
, typename mpl::select_type<
back_ref
, back_reference_arg_from_python<T>
, arg_rvalue_from_python<T>
>::type
>::type
>::type
>::type
>::type
>::type type;
>::type type;
};
// ==================

View File

@@ -0,0 +1,105 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
# define OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/detail/referent_storage.hpp>
# include <boost/python/detail/destroy.hpp>
# include <boost/python/detail/construct.hpp>
# include <boost/python/converter/object_manager.hpp>
//
// arg_from_python converters for Python type wrappers, to be used as
// base classes for specializations.
//
namespace boost { namespace python { namespace converter {
template <class T>
struct object_manager_value_arg_from_python
{
typedef T result_type;
object_manager_value_arg_from_python(PyObject*);
bool convertible() const;
T operator()(PyObject*) const;
private:
PyObject* m_source;
};
template <class Ref>
struct object_manager_ref_arg_from_python
{
typedef Ref result_type;
object_manager_ref_arg_from_python(PyObject*);
bool convertible() const;
Ref operator()(PyObject*) const;
~object_manager_ref_arg_from_python();
private:
typename python::detail::referent_storage<Ref>::type m_result;
};
//
// implementations
//
template <class T>
inline object_manager_value_arg_from_python<T>::object_manager_value_arg_from_python(PyObject* x)
: m_source(x)
{
}
template <class T>
inline bool object_manager_value_arg_from_python<T>::convertible() const
{
return extract_object_manager<T>::check(m_source);
}
template <class T>
inline T object_manager_value_arg_from_python<T>::operator()(PyObject* x) const
{
return T(python::detail::borrowed_reference(x));
}
template <class Ref>
inline object_manager_ref_arg_from_python<Ref>::object_manager_ref_arg_from_python(PyObject* x)
{
python::detail::construct_referent<Ref>(&m_result.bytes, python::detail::borrowed_reference(x));
}
template <class Ref>
inline object_manager_ref_arg_from_python<Ref>::~object_manager_ref_arg_from_python()
{
python::detail::destroy_referent<Ref>(this->m_result.bytes);
}
namespace detail
{
template <class T>
inline bool object_manager_ref_check(T const& x)
{
return extract_object_manager<T>::check((get_managed_object)(x));
}
}
template <class Ref>
inline bool object_manager_ref_arg_from_python<Ref>::convertible() const
{
return detail::object_manager_ref_check(
python::detail::void_ptr_to_reference(this->m_result.bytes, (Ref(*)())0));
}
template <class Ref>
inline Ref object_manager_ref_arg_from_python<Ref>::operator()(PyObject*) const
{
return python::detail::void_ptr_to_reference(
this->m_result.bytes, (Ref(*)())0);
}
}}} // namespace boost::python::converter
#endif // OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP

View File

@@ -12,22 +12,55 @@
# include <boost/mpl/select_type.hpp>
# include <boost/python/detail/indirect_traits.hpp>
namespace boost { namespace python { namespace api {
class object;
// Facilities for dealing with types which always manage Python
// objects. Some examples are object, list, et. al. Different
// to_python/from_python conversion rules apply here because in
// contrast to other types which are typically embedded inside a
// Python object, these are wrapped around a Python object. For most
// object managers T, a C++ non-const T reference argument does not
// imply the existence of a T lvalue embedded in the corresponding
// Python argument, since mutating member functions on T actually only
// modify the held Python object.
//
// Note also that handle<> does not qualify as an object manager because:
// a. It might not manage a Python object (it can be null)
// b. Mutating operations visible to users modify the handle<> itself.
namespace boost { namespace python { namespace api
{
class object; // forward declaration
}}}
namespace boost { namespace python { namespace converter {
// Used to create object managers of type T, taking ownership of a
// given PyObject*. Specializations X must satisfy the following,
// where p is a non-null PyObject*:
//
// X::is_specialized == true
//
// T(X::execute(p)) - constructs a T object from p, or throws a
// TypeError exception if p doesn't have an appropriate type.
//
// X::check(p), convertible to bool. True iff T(X::execute(p)) will
// not throw.
template <class T>
struct extract_object_manager
{
BOOST_STATIC_CONSTANT(bool, is_specialized = false);
};
// A metafunction returning true iff its argument is an object manager.
template <class T>
struct is_object_manager
{
private:
// handle the cases that would otherwise require partial specialization
BOOST_STATIC_CONSTANT(bool, hdl = is_handle<T>::value);
BOOST_STATIC_CONSTANT(bool, borrowed = python::detail::is_borrowed_ptr<T>::value);
BOOST_STATIC_CONSTANT(bool, extract_specialized = extract_object_manager<T>::is_specialized);
public:
BOOST_STATIC_CONSTANT(bool, value = (hdl | borrowed));
BOOST_STATIC_CONSTANT(bool, value = (hdl | borrowed | extract_specialized));
};
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION

View File

@@ -0,0 +1,48 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef PYTYPE_EXTRACT_OBJECT_MANAGER_DWA2002716_HPP
# define PYTYPE_EXTRACT_OBJECT_MANAGER_DWA2002716_HPP
# include <boost/python/converter/pytype_result_from_python.hpp>
# include <boost/python/detail/raw_pyobject.hpp>
# include <boost/python/cast.hpp>
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python { namespace converter {
// Provide a forward declaration as a convenience for clients, who all
// need it.
template <class T> struct extract_object_manager;
// Derive specializations of extract_object_manager from this class
// when T is an object manager for a particular Python type hierarchy.
//
template <PyTypeObject* pytype, class T>
struct pytype_extract_object_manager
{
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
static inline python::detail::new_reference execute(PyObject*);
static inline bool check(PyObject* x);
};
//
// implementations
//
template <PyTypeObject* pytype, class T>
inline python::detail::new_reference pytype_extract_object_manager<pytype,T>::execute(PyObject* x)
{
return pytype_result_from_python(pytype, x);
}
template <PyTypeObject* pytype, class T>
inline bool pytype_extract_object_manager<pytype,T>::check(PyObject* x)
{
return ::PyObject_IsInstance(x, python::upcast<PyObject>(pytype));
}
}}} // namespace boost::python::converter
#endif // PYTYPE_EXTRACT_OBJECT_MANAGER_DWA2002716_HPP

View File

@@ -6,6 +6,7 @@
#ifndef RETURN_FROM_PYTHON_DWA200265_HPP
# define RETURN_FROM_PYTHON_DWA200265_HPP
# include <boost/python/converter/object_manager.hpp>
# include <boost/python/converter/from_python.hpp>
# include <boost/python/converter/rvalue_from_python_data.hpp>
# include <boost/python/converter/registered.hpp>
@@ -42,9 +43,19 @@ namespace detail
rvalue_from_python_data<T> m_data;
};
template <class T>
struct return_object_manager_from_python
{
typedef T result_type;
result_type operator()(PyObject*) const;
};
template <class T>
struct select_return_from_python
{
BOOST_STATIC_CONSTANT(
bool, obj_mgr = is_object_manager<T>::value);
BOOST_STATIC_CONSTANT(
bool, ptr = is_pointer<T>::value);
@@ -52,14 +63,18 @@ namespace detail
bool, ref = is_reference<T>::value);
typedef typename mpl::select_type<
ptr
, return_pointer_from_python<T>
obj_mgr
, return_object_manager_from_python<T>
, typename mpl::select_type<
ref
, return_reference_from_python<T>
, return_rvalue_from_python<T>
ptr
, return_pointer_from_python<T>
, typename mpl::select_type<
ref
, return_reference_from_python<T>
, return_rvalue_from_python<T>
>::type
>::type
>::type type;
>::type type;
};
}
@@ -120,6 +135,14 @@ namespace detail
(pointer_result_from_python)(obj, registered_pointee<T>::converters)
);
}
template <class T>
inline T return_object_manager_from_python<T>::operator()(PyObject* obj) const
{
return T(
extract_object_manager<T>::execute(obj)
);
}
}
}}} // namespace boost::python::converter

View File

@@ -0,0 +1,37 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#ifndef CONSTRUCT_REFERENCE_DWA2002716_HPP
# define CONSTRUCT_REFERENCE_DWA2002716_HPP
namespace boost { namespace python { namespace detail {
template <class T, class Arg>
void construct_pointee(void* storage, Arg& x, T const volatile*)
{
new (storage) T(x);
}
template <class T, class Arg>
void construct_referent_impl(void* storage, Arg& x, T&(*)())
{
construct_pointee(storage, x, (T*)0);
}
template <class T, class Arg>
void construct_referent(void* storage, Arg const& x, T(*tag)() = 0)
{
construct_referent_impl(storage, x, tag);
}
template <class T, class Arg>
void construct_referent(void* storage, Arg& x, T(*tag)() = 0)
{
construct_referent_impl(storage, x, tag);
}
}}} // namespace boost::python::detail
#endif // CONSTRUCT_REFERENCE_DWA2002716_HPP

View File

@@ -16,7 +16,7 @@ namespace boost { namespace python { namespace detail {
// friendship to all the appropriate parties.
//
// New references are checked for null
// New references are normally checked for null
struct new_reference_t;
typedef new_reference_t* new_reference;
@@ -24,6 +24,10 @@ typedef new_reference_t* new_reference;
struct borrowed_reference_t;
typedef borrowed_reference_t* borrowed_reference;
// New references which aren't checked for null
struct new_non_null_reference_t;
typedef new_non_null_reference_t* new_non_null_reference;
}}} // namespace boost::python::detail
#endif // RAW_PYOBJECT_DWA2002628_HPP

View File

@@ -7,8 +7,7 @@
# define LIST_DWA2002627_HPP
# include <boost/python/object.hpp>
# include <boost/python/converter/pytype_arg_from_python.hpp>
# include <boost/python/converter/pytype_result_from_python.hpp>
# include <boost/python/converter/pytype_extract_object_manager.hpp>
namespace boost { namespace python {
@@ -95,81 +94,24 @@ class list : public object
}
public: // implementation detail -- for internal use only
inline explicit list(detail::borrowed_reference);
inline explicit list(detail::new_reference);
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(list)
private:
static BOOST_PYTHON_DECL detail::new_reference call(object const&);
static BOOST_PYTHON_DECL detail::new_non_null_reference call(object const&);
};
//
// Converter Specializations
//
template <class T> struct arg_from_python;
template <>
struct arg_from_python<list>
: converter::pytype_wrapper_value_arg_from_python<list, &PyList_Type>
{
typedef converter::pytype_wrapper_value_arg_from_python<list, &PyList_Type> base;
typedef list result_type;
arg_from_python(PyObject* p) : base(p) {}
};
template <>
struct arg_from_python<list const&>
: arg_from_python<list>
{
arg_from_python(PyObject* p)
: arg_from_python<list>(p) {}
};
template <>
struct arg_from_python<list&>
: converter::pytype_wrapper_ref_arg_from_python<list, &PyList_Type>
{
typedef converter::pytype_wrapper_ref_arg_from_python<list, &PyList_Type> base;
typedef list result_type;
arg_from_python(PyObject* p)
: base(p) {}
};
namespace converter
{
template <class T> struct is_object_manager;
template <>
struct is_object_manager<list>
struct extract_object_manager<list>
: pytype_extract_object_manager<&PyList_Type,list>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class T> struct return_from_python;
template <>
struct return_from_python<list>
{
typedef list result_type;
result_type operator()(PyObject* x) const
{
return list((pytype_result_from_python)(&PyList_Type, x));
}
};
}
//
// list implementation
//
inline list::list(detail::borrowed_reference p)
: object(p)
{}
inline list::list(detail::new_reference p)
: object(p)
{}
}} // namespace boost::python
#endif // LIST_DWA2002627_HPP

View File

@@ -7,8 +7,7 @@
# define LONG_DWA2002627_HPP
# include <boost/python/object.hpp>
# include <boost/python/converter/pytype_arg_from_python.hpp>
# include <boost/python/converter/pytype_result_from_python.hpp>
# include <boost/python/converter/pytype_extract_object_manager.hpp>
namespace boost { namespace python {
@@ -32,82 +31,25 @@ class long_ : public object
{
}
public: // implementation detail -- for internal use only
explicit inline long_(detail::borrowed_reference);
explicit inline long_(detail::new_reference);
BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(long_)
private:
static BOOST_PYTHON_DECL detail::new_reference call(object const&);
static BOOST_PYTHON_DECL detail::new_reference call(object const&, object const&);
static BOOST_PYTHON_DECL detail::new_non_null_reference call(object const&);
static BOOST_PYTHON_DECL detail::new_non_null_reference call(object const&, object const&);
};
//
// Converter Specializations
//
template <class T> struct arg_from_python;
template <>
struct arg_from_python<long_>
: converter::pytype_wrapper_value_arg_from_python<long_, &PyLong_Type>
{
typedef converter::pytype_wrapper_value_arg_from_python<long_, &PyLong_Type> base;
typedef long_ result_type;
arg_from_python(PyObject* p) : base(p) {}
};
template <>
struct arg_from_python<long_ const&>
: arg_from_python<long_>
{
arg_from_python(PyObject* p)
: arg_from_python<long_>(p) {}
};
template <>
struct arg_from_python<long_&>
: converter::pytype_wrapper_ref_arg_from_python<long_, &PyLong_Type>
{
typedef converter::pytype_wrapper_ref_arg_from_python<long_, &PyLong_Type> base;
typedef long_ result_type;
arg_from_python(PyObject* p)
: base(p) {}
};
namespace converter
{
template <class T> struct is_object_manager;
template <>
struct is_object_manager<long_>
struct extract_object_manager<long_>
: pytype_extract_object_manager<&PyLong_Type,long_>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class T> struct return_from_python;
template <>
struct return_from_python<long_>
{
typedef long_ result_type;
result_type operator()(PyObject* x) const
{
return long_((pytype_result_from_python)(&PyLong_Type, x));
}
};
}
//
// long_ implementation
//
inline long_::long_(detail::borrowed_reference p)
: object(p)
{}
inline long_::long_(detail::new_reference p)
: object(p)
{}
}} // namespace boost::python
#endif // LONG_DWA2002627_HPP

View File

@@ -14,6 +14,7 @@
# include <boost/python/slice_nil.hpp>
# include <boost/python/detail/raw_pyobject.hpp>
# include <boost/python/refcount.hpp>
# include <boost/python/converter/always_extract_object_manager.hpp>
# include <boost/python/detail/preprocessor.hpp>
# include <boost/preprocessor/iterate.hpp>
@@ -227,8 +228,18 @@ namespace api
public: // implementation detail -- for internal use only
explicit object(detail::borrowed_reference);
explicit object(detail::new_reference);
explicit object(detail::new_non_null_reference);
};
// Derived classes will usually want these as an implementation detail
# define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(derived) \
inline explicit derived(python::detail::borrowed_reference p) \
: object(p) {} \
inline explicit derived(python::detail::new_reference p) \
: object(p) {} \
inline explicit derived(python::detail::new_non_null_reference p) \
: object(p) {}
//
// object_initializer -- get the handle to construct the object with,
// based on whether T is a proxy or derived from object
@@ -266,53 +277,13 @@ using api::object;
//
// Converter Specializations
//
template <class T> struct arg_from_python;
template <>
struct arg_from_python<object>
{
typedef object result_type;
arg_from_python(PyObject*);
bool convertible() const;
object operator()(PyObject* x) const;
};
template <>
struct arg_from_python<object const&>
: arg_from_python<object>
{
arg_from_python(PyObject*);
};
template <>
struct arg_from_python<object&>
{
typedef object& result_type;
arg_from_python(PyObject*);
bool convertible() const;
object& operator()(PyObject* x) const;
private:
mutable object m_result;
};
namespace converter
{
template <class T> struct is_object_manager;
template <>
struct is_object_manager<object>
struct extract_object_manager<object>
: always_extract_object_manager
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class T> struct return_from_python;
template <>
struct return_from_python<object>
{
typedef object result_type;
result_type operator()(PyObject* x) const;
static python::detail::borrowed_reference execute(PyObject* x);
};
}
@@ -345,7 +316,6 @@ inline api::object_base& api::object_base::operator=(api::object_base const& rhs
return *this;
}
inline api::object_base::~object_base()
{
Py_DECREF(m_ptr);
@@ -360,6 +330,10 @@ inline object::object(detail::new_reference p)
: object_base(expect_non_null((PyObject*)p))
{}
inline object::object(detail::new_non_null_reference p)
: object_base((PyObject*)p)
{}
inline PyObject* api::object_base::ptr() const
{
return m_ptr;
@@ -368,45 +342,14 @@ inline PyObject* api::object_base::ptr() const
//
// Converter specialization implementations
//
inline arg_from_python<object>::arg_from_python(PyObject*)
{}
inline bool arg_from_python<object>::convertible() const
{
return true;
}
inline object arg_from_python<object>::operator()(PyObject* x) const
{
return object(detail::borrowed_reference(x));
}
inline arg_from_python<object const&>::arg_from_python(PyObject*)
: arg_from_python<object>(0)
{}
inline arg_from_python<object&>::arg_from_python(PyObject* x)
: m_result(detail::borrowed_reference(x))
{}
inline bool arg_from_python<object&>::convertible() const
{
return true;
}
inline object& arg_from_python<object&>::operator()(PyObject* x) const
{
return m_result;
}
namespace converter
{
inline object
return_from_python<object>::operator()(PyObject* x) const
inline python::detail::borrowed_reference
extract_object_manager<object>::execute(PyObject* x)
{
return object(python::detail::new_reference(x));
return python::detail::borrowed_reference(python::incref(x));
}
inline PyObject* get_managed_object(object const& x)
{
return x.ptr();

View File

@@ -7,11 +7,13 @@
namespace boost { namespace python {
BOOST_PYTHON_DECL detail::new_reference list::call(object const& arg)
BOOST_PYTHON_DECL detail::new_non_null_reference list::call(object const& arg)
{
return (detail::new_reference)PyObject_CallFunction(
(PyObject*)&PyList_Type, "(O)",
arg.ptr());
return (detail::new_non_null_reference)
(expect_non_null)(
PyObject_CallFunction(
(PyObject*)&PyList_Type, "(O)",
arg.ptr()));
}
BOOST_PYTHON_DECL list::list()

View File

@@ -7,16 +7,16 @@
namespace boost { namespace python {
BOOST_PYTHON_DECL detail::new_reference long_::call(object const& arg)
BOOST_PYTHON_DECL detail::new_non_null_reference long_::call(object const& arg)
{
return (detail::new_reference)PyObject_CallFunction(
return (detail::new_non_null_reference)PyObject_CallFunction(
(PyObject*)&PyLong_Type, "(O)",
arg.ptr());
}
BOOST_PYTHON_DECL detail::new_reference long_::call(object const& arg, object const& base)
BOOST_PYTHON_DECL detail::new_non_null_reference long_::call(object const& arg, object const& base)
{
return (detail::new_reference)PyObject_CallFunction(
return (detail::new_non_null_reference)PyObject_CallFunction(
(PyObject*)&PyLong_Type, "(OO)",
arg.ptr(), base.ptr());
}