2
0
mirror of https://github.com/boostorg/python.git synced 2026-02-01 20:52:13 +00:00

beginning of object support

[SVN r14157]
This commit is contained in:
Dave Abrahams
2002-06-16 20:41:54 +00:00
parent 0b5937a396
commit c12ffa21da
44 changed files with 1895 additions and 179 deletions

View File

@@ -27,6 +27,7 @@ dll bpl
src/converter/builtin_converters.cpp
src/converter/callback.cpp
src/object/iterator.cpp
src/object_protocol.cpp
:
$(BOOST_PYTHON_V2_PROPERTIES)
<define>BOOST_PYTHON_SOURCE

View File

@@ -0,0 +1,36 @@
// 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 BASE_TYPE_TRAITS_DWA2002614_HPP
# define BASE_TYPE_TRAITS_DWA2002614_HPP
namespace boost { namespace python {
namespace detail
{
struct unspecialized {};
}
// Derive from unspecialized so we can detect whether traits are
// specialized
template <class T> struct base_type_traits
: detail::unspecialized
{};
template <>
struct base_type_traits<PyObject>
{
typedef PyObject type;
};
template <>
struct base_type_traits<PyTypeObject>
{
typedef PyObject type;
};
}} // namespace boost::python
#endif // BASE_TYPE_TRAITS_DWA2002614_HPP

View File

@@ -9,38 +9,13 @@
# include <boost/python/detail/wrap_python.hpp>
# include <boost/type_traits/same_traits.hpp>
# include <boost/type.hpp>
# include <boost/python/base_type_traits.hpp>
# include <boost/python/detail/convertible.hpp>
namespace boost { namespace python {
template <class T> struct base_type_traits;
template <>
struct base_type_traits<PyObject>
{
typedef PyObject type;
};
template <>
struct base_type_traits<PyTypeObject>
{
typedef PyObject type;
};
namespace detail
{
typedef char* yes_convertible;
typedef int* no_convertible;
typedef char* yes_python_object;
typedef int* no_python_object;
template <class Target>
struct convertible
{
static inline yes_convertible check(Target) { return 0; }
static inline no_convertible check(...) { return 0; }
};
template <class Target>
inline Target* upcast(Target* p, yes_convertible)
{

View File

@@ -10,7 +10,11 @@
# include <boost/python/converter/to_python_function.hpp>
# include <boost/python/converter/pointee_to_python_function.hpp>
# include <boost/python/converter/arg_to_python_base.hpp>
# include <boost/python/converter/object_manager.hpp>
# include <boost/python/to_python_indirect.hpp>
# include <boost/type_traits/cv_traits.hpp>
# include <boost/python/detail/convertible.hpp>
# include <boost/python/base_type_traits.hpp>
// Bring in specializations
# include <boost/python/converter/builtin_converters.hpp>
@@ -51,9 +55,27 @@ namespace detail
static PyObject* get_object(Ptr p);
};
// Convert types that manage a Python object to_python
template <class T>
struct object_manager_arg_to_python
{
object_manager_arg_to_python(T const& x) : m_src(x) {}
PyObject* get() const
{
return python::upcast<PyObject>(converter::get_managed_object(m_src));
}
private:
T const& m_src;
};
template <class T>
struct select_arg_to_python
{
BOOST_STATIC_CONSTANT(
bool, manager = is_object_manager<T>::value);
BOOST_STATIC_CONSTANT(
bool, ptr = is_pointer<T>::value);
@@ -67,15 +89,19 @@ namespace detail
typedef typename unwrap_pointer<T>::type unwrapped_ptr;
typedef typename mpl::select_type<
ptr
, pointer_deep_arg_to_python<T>
manager
, object_manager_arg_to_python<T>
, typename mpl::select_type<
ptr_wrapper
, pointer_shallow_arg_to_python<unwrapped_ptr>
ptr
, pointer_deep_arg_to_python<T>
, typename mpl::select_type<
ref_wrapper
, reference_arg_to_python<unwrapped_referent>
, value_arg_to_python<T>
ptr_wrapper
, pointer_shallow_arg_to_python<unwrapped_ptr>
, typename mpl::select_type<
ref_wrapper
, reference_arg_to_python<unwrapped_referent>
, value_arg_to_python<T>
>::type
>::type
>::type
>::type type;
@@ -108,6 +134,39 @@ struct arg_to_python
//
namespace detail
{
// reject_raw_object_ptr -- cause a compile-time error if the user
// should pass a raw Python object pointer
using python::detail::yes_convertible;
using python::detail::no_convertible;
using python::detail::unspecialized;
template <class T> struct cannot_convert_raw_PyObject;
template <class T, class Convertibility>
struct reject_raw_object_helper
{
static void error(Convertibility)
{
cannot_convert_raw_PyObject<T*>::to_python_use_handle_instead();
}
static void error(...) {}
};
template <class T>
inline void reject_raw_object_ptr(T*)
{
reject_raw_object_helper<T,yes_convertible>::error(
python::detail::convertible<PyObject const volatile*>::check((T*)0));
typedef typename remove_cv<T>::type value_type;
reject_raw_object_helper<T,no_convertible>::error(
python::detail::convertible<unspecialized*>::check(
(base_type_traits<value_type>*)0
));
}
// ---------
template <class T>
inline value_arg_to_python<T>::value_arg_to_python(T const& x)
: arg_to_python_base(&x, to_python_function<T>::value)
@@ -118,6 +177,7 @@ namespace detail
inline pointer_deep_arg_to_python<Ptr>::pointer_deep_arg_to_python(Ptr x)
: arg_to_python_base(x, pointee_to_python_function<Ptr>::value)
{
detail::reject_raw_object_ptr((Ptr)0);
}
template <class T>
@@ -131,14 +191,16 @@ namespace detail
template <class T>
inline reference_arg_to_python<T>::reference_arg_to_python(T& x)
: handle<>(get_object(x))
: handle<>(reference_arg_to_python<T>::get_object(x))
{
}
template <class Ptr>
inline pointer_shallow_arg_to_python<Ptr>::pointer_shallow_arg_to_python(Ptr x)
: handle<>(get_object(x))
{}
: handle<>(pointer_shallow_arg_to_python<Ptr>::get_object(x))
{
detail::reject_raw_object_ptr((Ptr)0);
}
template <class Ptr>
inline PyObject* pointer_shallow_arg_to_python<Ptr>::get_object(Ptr x)

View File

@@ -13,9 +13,18 @@ namespace boost { namespace python { namespace converter {
namespace detail
{
struct BOOST_PYTHON_DECL arg_to_python_base : handle<>
struct BOOST_PYTHON_DECL arg_to_python_base
# if !defined(BOOST_MSVC) || _MSC_FULL_VER != 13102140
: handle<>
# endif
{
arg_to_python_base(void const volatile* source, to_python_function_t);
# if defined(BOOST_MSVC) && _MSC_FULL_VER == 13102140
PyObject* get() const { return m_ptr.get(); }
PyObject* release() { return m_ptr.release(); }
private:
handle<> m_ptr;
# endif
};
}

View File

@@ -105,7 +105,6 @@ BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x))
BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(PyObject*, converter::do_return_to_python(x))
BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(PyObject*, converter::do_arg_to_python(x))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<float>, PyComplex_FromDoubles(x.real(), x.imag()))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<double>, PyComplex_FromDoubles(x.real(), x.imag()))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<long double>, PyComplex_FromDoubles(x.real(), x.imag()))

View File

@@ -1,3 +1,4 @@
#error obsolete
// 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

View File

@@ -0,0 +1,149 @@
// 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 OBJECT_MANAGER_DWA2002614_HPP
# define OBJECT_MANAGER_DWA2002614_HPP
# include <boost/python/handle.hpp>
# include <boost/python/cast.hpp>
# include <boost/type_traits/object_traits.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/python/detail/indirect_traits.hpp>
namespace boost { namespace python {
class object;
}}
namespace boost { namespace python { namespace converter {
template <class T>
class is_object_manager
{
BOOST_STATIC_CONSTANT(bool, hdl = is_handle<T>::value);
BOOST_STATIC_CONSTANT(bool, borrowed = python::detail::is_borrowed_ptr<T>::value);
public:
BOOST_STATIC_CONSTANT(bool, value = (hdl | borrowed));
};
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct is_reference_to_object_manager
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class T>
struct is_reference_to_object_manager<T&>
: is_object_manager<T>
{
};
template <class T>
struct is_reference_to_object_manager<T const&>
: is_object_manager<T>
{
};
template <class T>
struct is_reference_to_object_manager<T volatile&>
: is_object_manager<T>
{
};
template <class T>
struct is_reference_to_object_manager<T const volatile&>
: is_object_manager<T>
{
};
# else
namespace detail
{
typedef char (&yes_reference_to_object_manager)[1];
typedef char (&no_reference_to_object_manager)[2];
template <class T>
struct is_object_manager_help
: mpl::select_type<
is_object_manager<T>::value
, yes_reference_to_object_manager
, no_reference_to_object_manager>
{
};
template <bool is_ref = false>
struct is_reference_to_object_manager_helper
{
template <class T>
struct apply
{
static int x;
static no_reference_to_object_manager check(...);
};
};
template <class U>
typename is_object_manager_help<U>::type
is_object_manager_helper(int*, double, double, U&);
template <class U>
typename is_object_manager_help<U>::type
is_object_manager_helper(int*, int*, double, U const&);
template <class U>
typename is_object_manager_help<U>::type
is_object_manager_helper(int*, double, int*, U volatile&);
template <class U>
typename is_object_manager_help<U>::type
is_object_manager_helper(int*, int*, int*, U const volatile&);
no_reference_to_object_manager is_object_manager_helper(...);
}
template <class T>
struct is_reference_to_object_manager
{
typedef typename mpl::select_type<
is_reference<T>::value, int*, double>::type r_t;
typedef typename mpl::select_type<
python::detail::is_reference_to_const<T>::value, int*, double>::type rc_t;
typedef typename mpl::select_type<
python::detail::is_reference_to_volatile<T>::value, int*, double>::type rv_t;
typedef typename mpl::select_type<is_reference<T>::value, T, int>::type value_t;
static value_t sample_object;
BOOST_STATIC_CONSTANT(
bool, value
= (sizeof(detail::is_object_manager_helper(r_t(),rc_t(),rv_t(),sample_object))
== sizeof(detail::yes_reference_to_object_manager)
)
);
};
# endif
template <class T>
inline T* get_managed_object(handle<T> const& h)
{
return h.get();
}
template <class T>
inline T* get_managed_object(python::detail::borrowed<T> const volatile* p)
{
return (T*)p;
}
// forward declaration needed because name lookup is bound by the
// definition context.
PyObject* get_managed_object(python::object const&);
}}} // namespace boost::python::converter
#endif // OBJECT_MANAGER_DWA2002614_HPP

View File

@@ -7,6 +7,10 @@
# define RETURN_FROM_PYTHON_DWA200265_HPP
# include <boost/python/converter/callback_from_python_base.hpp>
# include <boost/python/converter/from_python_data.hpp>
# include <boost/python/converter/rvalue_from_python_chain.hpp>
# include <boost/python/converter/lvalue_from_python_chain.hpp>
# include <boost/python/detail/void_ptr.hpp>
namespace boost { namespace python { namespace converter {

View File

@@ -0,0 +1,56 @@
#ifndef BORROWED_PTR_DWA20020601_HPP
# define BORROWED_PTR_DWA20020601_HPP
// 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.
# include <boost/config.hpp>
#include <boost/type.hpp>
namespace boost { namespace python { namespace detail {
template<class T> class borrowed
{
typedef T type;
};
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<typename T>
struct is_borrowed_ptr
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template<typename T>
struct is_borrowed_ptr<borrowed<T>*>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
# else // no partial specialization
typedef char (&yes_borrowed_ptr_t)[1];
typedef char (&no_borrowed_ptr_t)[2];
no_borrowed_ptr_t is_borrowed_ptr_test(...);
template<typename T>
yes_borrowed_ptr_t is_borrowed_ptr_test(boost::type< borrowed<T>* >);
template<typename T>
class is_borrowed_ptr
{
public:
BOOST_STATIC_CONSTANT(
bool, value = (
sizeof(detail::is_borrowed_ptr_test(boost::type<T>()))
== sizeof(detail::yes_borrowed_ptr_t)));
};
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
}}} // namespace boost::python::detail
#endif // #ifndef BORROWED_PTR_DWA20020601_HPP

View File

@@ -0,0 +1,25 @@
// 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 CONVERTIBLE_DWA2002614_HPP
# define CONVERTIBLE_DWA2002614_HPP
// Supplies a runtime is_convertible check which can be used with tag
// dispatching to work around the Metrowerks Pro7 limitation with boost::is_convertible
namespace boost { namespace python { namespace detail {
typedef char* yes_convertible;
typedef int* no_convertible;
template <class Target>
struct convertible
{
static inline yes_convertible check(Target) { return 0; }
static inline no_convertible check(...) { return 0; }
};
}}} // namespace boost::python::detail
#endif // CONVERTIBLE_DWA2002614_HPP

View File

@@ -26,7 +26,7 @@ struct is_reference_to_const<T const&>
BOOST_STATIC_CONSTANT(bool, value = true);
};
# if defined(BOOST_MSVC) && _MSC_FULL_VER <= 13012108 // vc7.01 alpha workaround
# if defined(BOOST_MSVC) && _MSC_FULL_VER <= 13102140 // vc7.01 alpha workaround
template<class T>
struct is_reference_to_const<T const volatile&>
{
@@ -121,7 +121,7 @@ struct is_reference_to_volatile<T volatile&>
BOOST_STATIC_CONSTANT(bool, value = true);
};
# if defined(BOOST_MSVC) && _MSC_FULL_VER <= 13012108 // vc7.01 alpha workaround
# if defined(BOOST_MSVC) && _MSC_FULL_VER <= 13102140 // vc7.01 alpha workaround
template <class T>
struct is_reference_to_volatile<T const volatile&>
{

View File

@@ -133,7 +133,7 @@ struct unwind_helper2<reference_to_pointer_>
// why bother?
template <class Generator, class U>
inline typename Generator::result_type
unwind_type(type<U>*p = 0, Generator* = 0)
unwind_type(boost::type<U>*p = 0, Generator* = 0)
{
BOOST_STATIC_CONSTANT(int, indirection
= (is_pointer<U>::value ? pointer_ : 0)

View File

@@ -9,44 +9,14 @@
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/cast.hpp>
# include <boost/python/errors.hpp>
# include <boost/python/borrowed.hpp>
# include <boost/python/handle_fwd.hpp>
# include <boost/python/refcount.hpp>
namespace boost { namespace python {
template <class T>
inline T* incref(T* p)
{
Py_INCREF(python::upcast<PyObject>(p));
return p;
}
template <class T>
inline T* xincref(T* p)
{
Py_XINCREF(python::upcast<PyObject>(p));
return p;
}
template <class T>
inline void decref(T* p)
{
Py_DECREF(python::upcast<PyObject>(p));
}
template <class T>
inline void xdecref(T* p)
{
Py_XDECREF(python::upcast<PyObject>(p));
}
template <class T> struct borrowed;
template <class T> struct null_ok;
template <class T>
inline borrowed<T>* borrow(T* p)
{
return (borrowed<T>*)p;
}
template <class T>
inline null_ok<T>* allow_null(T* p)
{
@@ -56,19 +26,19 @@ inline null_ok<T>* allow_null(T* p)
namespace detail
{
template <class T>
inline T* manage_ptr(borrowed<null_ok<T> >* p, int)
inline T* manage_ptr(detail::borrowed<null_ok<T> >* p, int)
{
return python::xincref((T*)p);
}
template <class T>
inline T* manage_ptr(null_ok<borrowed<T> >* p, int)
inline T* manage_ptr(null_ok<detail::borrowed<T> >* p, int)
{
return python::xincref((T*)p);
}
template <class T>
inline T* manage_ptr(borrowed<T>* p, long)
inline T* manage_ptr(detail::borrowed<T>* p, long)
{
return python::incref(expect_non_null((T*)p));
}
@@ -84,31 +54,9 @@ namespace detail
{
return expect_non_null(p);
}
#if 0
template <class T>
struct handle_proxy
: handle_proxy<typename base_type_traits<T>::type>
{
typedef typename base_type_traits<T>::type base_t;
handle_proxy(PyObject* p)
: handle_proxy<base_t>(p)
{}
operator T*() const { return python::downcast<T>(m_p); }
};
template <>
struct handle_proxy<PyObject>
{
handle_proxy(PyObject* p) : m_p(p) {}
operator PyObject*() const { return (PyObject*)m_p; }
private:
PyObject* m_p;
};
#endif
}
template <class T = PyObject>
template <class T>
class handle
{
typedef T* (handle::*bool_type);
@@ -153,6 +101,7 @@ class handle
}
T* operator-> () const;
T& operator* () const;
T* get() const;
T* release();
@@ -168,6 +117,79 @@ class handle
typedef handle<PyTypeObject> type_handle;
//
// Converter specializations
//
template <class T> struct arg_from_python;
template <>
struct arg_from_python<handle<> >
{
typedef handle<> result_type;
arg_from_python(PyObject*);
bool convertible() const;
handle<> operator()(PyObject* x) const;
};
template <>
struct arg_from_python<handle<> const&>
: arg_from_python<handle<> >
{
arg_from_python(PyObject*);
};
namespace converter
{
template <class T> struct return_from_python;
template <>
struct return_from_python<handle<> >
{
typedef handle<> result_type;
result_type operator()(PyObject* x) const;
};
}
//
// Compile-time introspection
//
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<typename T>
class is_handle
{
public:
BOOST_STATIC_CONSTANT(bool, value = false);
};
template<typename T>
class is_handle<handle<T> >
{
public:
BOOST_STATIC_CONSTANT(bool, value = true);
};
# else
namespace detail
{
typedef char (&yes_handle_t)[1];
typedef char (&no_handle_t)[2];
no_handle_t is_handle_test(...);
template<typename T>
yes_handle_t is_handle_test(boost::type< handle<T> >);
}
template<typename T>
class is_handle
{
public:
BOOST_STATIC_CONSTANT(
bool, value = (
sizeof(detail::is_handle_test(boost::type<T>()))
== sizeof(detail::yes_handle_t)));
};
# endif
//
// implementations
//
@@ -197,6 +219,12 @@ inline T* handle<T>::operator->() const
return m_p;
}
template <class T>
inline T& handle<T>::operator*() const
{
return *m_p;
}
template <class T>
inline T* handle<T>::get() const
{
@@ -217,6 +245,35 @@ inline T* handle<T>::release()
return result;
}
//
// Converter specialization implementation
//
inline arg_from_python<handle<> >::arg_from_python(PyObject*)
{}
inline bool arg_from_python<handle<> >::convertible() const
{
return true;
}
inline handle<> arg_from_python<handle<> >::operator()(PyObject* x) const
{
return handle<>(python::borrowed(python::allow_null(x)));
}
inline arg_from_python<handle<> const&>::arg_from_python(PyObject*)
: arg_from_python<handle<> >(0)
{}
namespace converter
{
inline handle<>
return_from_python<handle<> >::operator()(PyObject* x) const
{
return handle<>(x);
}
}
}} // namespace boost::python

View File

@@ -0,0 +1,17 @@
// 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 HANDLE_FWD_DWA2002615_HPP
# define HANDLE_FWD_DWA2002615_HPP
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python {
template <class T = PyObject> class handle;
}} // namespace boost::python
#endif // HANDLE_FWD_DWA2002615_HPP

20
include/boost/python/object.hpp Executable file
View File

@@ -0,0 +1,20 @@
// 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 OBJECT_DWA2002612_HPP
# define OBJECT_DWA2002612_HPP
# include <boost/python/object_core.hpp>
# include <boost/python/object_attributes.hpp>
# include <boost/python/object_items.hpp>
namespace boost { namespace python {
class string;
class type;
}} // namespace boost::python
#endif // OBJECT_DWA2002612_HPP

View File

@@ -61,7 +61,7 @@ namespace detail
no_reference_to_value_t is_reference_to_value_test(...);
template<typename T>
yes_reference_to_value_t is_reference_to_value_test(type< reference_to_value<T> >);
yes_reference_to_value_t is_reference_to_value_test(boost::type< reference_to_value<T> >);
template<bool wrapped>
struct unforwarder
@@ -89,7 +89,7 @@ namespace detail
public:
BOOST_STATIC_CONSTANT(
bool, value = (
sizeof(is_reference_to_value_test(type<T>()))
sizeof(is_reference_to_value_test(boost::type<T>()))
== sizeof(yes_reference_to_value_t)));
};
}

View File

@@ -174,7 +174,7 @@ namespace detail
// Build and convert the iterator_range<>.
return cr(
iterator_range<NextPolicies,Iterator>(
handle<>(python::borrow(arg0))
handle<>(python::borrowed(arg0))
, get_start(x), get_finish(x)));
}
};

View File

@@ -0,0 +1,81 @@
// 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 OBJECT_ATTRIBUTES_DWA2002615_HPP
# define OBJECT_ATTRIBUTES_DWA2002615_HPP
# include <boost/python/proxy.hpp>
# include <boost/python/object_core.hpp>
# include <boost/python/object_protocol.hpp>
namespace boost { namespace python {
namespace detail
{
struct const_attribute_policies
{
static object get(object const& target, object const& key);
};
struct attribute_policies : const_attribute_policies
{
static object const& set(object const& target, object const& key, object const& value);
};
}
//
// implementation
//
inline object_attribute object::_(char const* name)
{
return object_attribute(*this, object(name));
}
inline const_object_attribute object::_(char const* name) const
{
return const_object_attribute(*this, object(name));
}
namespace detail
{
inline object const_attribute_policies::get(object const& target, object const& key)
{
return python::getattr(target, key);
}
inline object const& attribute_policies::set(
object const& target
, object const& key
, object const& value)
{
python::setattr(target, key, value);
return value;
}
}
namespace converter
{
// These specializations are a lie; the proxies do not directly
// manage an object. What actually happens is that the implicit
// conversion to object takes hold and its conversion to_python is
// used. That's OK in part because the object temporary *is*
// actually managing the object during the duration of the
// conversion.
template <>
struct is_object_manager<object_attribute>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <>
struct is_object_manager<const_object_attribute>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
}
}} // namespace boost::python
#endif // OBJECT_ATTRIBUTES_DWA2002615_HPP

View File

@@ -0,0 +1,286 @@
// 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 OBJECT_CORE_DWA2002615_HPP
# define OBJECT_CORE_DWA2002615_HPP
# include <boost/python/handle.hpp>
# include <boost/python/converter/arg_to_python.hpp>
# include <boost/python/detail/preprocessor.hpp>
# include <boost/python/call.hpp>
namespace boost { namespace python {
// This file contains the definition of the object class and enough to
// construct/copy it, but not enough to do operations like
// attribute/item access or addition.
template <class Policies> class proxy;
namespace detail
{
struct const_attribute_policies;
struct attribute_policies;
struct const_item_policies;
struct item_policies;
}
typedef proxy<detail::const_attribute_policies> const_object_attribute;
typedef proxy<detail::attribute_policies> object_attribute;
typedef proxy<detail::const_item_policies> const_object_item;
typedef proxy<detail::item_policies> object_item;
class object
{
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200
typedef object const& self_cref;
# else
typedef object self_cref;
# endif
public:
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
// copy constructor without NULL checking, for efficiency
object(object const&);
# endif
// explicit conversion from any C++ object to Python
template <class T>
explicit object(T const& x)
: m_ptr(
python::borrowed(
python::allow_null( // null check is already done
converter::arg_to_python<T>(x).get())
)
)
{
}
// capture this case explicitly to handle string
// literals. Otherwise, they get deduced as char[N]const& above
// and conversion fails at runtime.
explicit object(char const* x)
: m_ptr(
python::borrowed(
python::allow_null( // null check is already done
converter::arg_to_python<char const*>(x).get())
)
)
{
}
// Throw error_already_set() if the handle is null.
explicit object(handle<> const&);
// Attribute access via x._("attribute_name")
const_object_attribute _(char const*) const;
object_attribute _(char const*);
object operator()() const
{
return object(call<handle<> >(m_ptr.get()));
}
# ifndef BOOST_PYTHON_GENERATE_CODE
# include <boost/python/preprocessed/object_call.hpp>
# endif
# define BOOST_PYTHON_OBJECT_CALL(nargs,ignored) \
template <BOOST_PP_ENUM_PARAMS(nargs, class A)> \
object operator()(BOOST_PYTHON_ENUM_PARAMS2(nargs, (A,const& a))) const \
{ \
return object(call<handle<> >(&**this, BOOST_PP_ENUM_PARAMS(nargs, a))); \
}
BOOST_PYTHON_REPEAT_ARITY_2ND(BOOST_PYTHON_OBJECT_CALL, ignored)
// truth value testing
typedef handle<> (object::*bool_type);
operator bool_type() const;
bool operator!() const; // needed for vc6
// item access
const_object_item operator[](self_cref) const;
object_item operator[](self_cref);
template <class T>
const_object_item operator[](T const& key) const
{
return (*this)[object(key)];
}
template <class T>
object_item operator[](T const& key)
{
return (*this)[object(key)];
}
// Underlying object access
PyObject* operator->() const;
PyObject& operator*() const;
public: // implementation detail -- for internal use only
object(null_ok<detail::borrowed<PyObject> >*);
object(detail::borrowed<null_ok<PyObject> >*);
object(detail::borrowed<PyObject>*);
class new_pyobject_reference;
object(new_pyobject_reference*);
private:
handle<> m_ptr;
};
//
// 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>
{
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;
};
}
//
// implementation
//
inline object::object(handle<> const& x)
: m_ptr(python::borrowed(x.get()))
{}
# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
// copy constructor without NULL checking, for efficiency
inline object::object(object const& rhs)
: m_ptr(python::allow_null(python::borrowed(&*rhs)))
{}
# endif
inline object::object(null_ok<detail::borrowed<PyObject> >* p)
: m_ptr(p)
{}
inline object::object(detail::borrowed<null_ok<PyObject> >* p)
: m_ptr(p)
{}
inline object::object(detail::borrowed<PyObject>* p)
: m_ptr(p)
{}
inline object::object(object::new_pyobject_reference* p)
: m_ptr((PyObject*)p)
{}
inline PyObject* object::operator->() const
{
return m_ptr.operator->();
}
inline PyObject& object::operator*() const
{
return *m_ptr;
}
inline object::operator object::bool_type() const
{
return PyObject_IsTrue(&**this) ? &object::m_ptr : 0;
}
inline bool object::operator!() const
{
return !PyObject_IsTrue(&**this);
}
//
// Converter speciaization 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(python::borrowed(python::allow_null(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(python::allow_null(python::borrowed(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
{
return object((object::new_pyobject_reference*)x);
}
inline PyObject* get_managed_object(object const& x)
{
return &*x;
}
}
}} // namespace boost::python
#endif // OBJECT_CORE_DWA2002615_HPP

View File

@@ -0,0 +1,81 @@
// 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 OBJECT_ITEMS_DWA2002615_HPP
# define OBJECT_ITEMS_DWA2002615_HPP
# include <boost/python/proxy.hpp>
# include <boost/python/object_core.hpp>
# include <boost/python/object_protocol.hpp>
namespace boost { namespace python {
namespace detail
{
struct const_item_policies
{
static object get(object const& target, object const& key);
};
struct item_policies : const_item_policies
{
static object const& set(object const& target, object const& key, object const& value);
};
}
//
// implementation
//
inline object_item object::operator[](object::self_cref key)
{
return object_item(*this, key);
}
inline const_object_item object::operator[](object::self_cref key) const
{
return const_object_item(*this, key);
}
namespace detail
{
inline object const_item_policies::get(object const& target, object const& key)
{
return python::getitem(target, key);
}
inline object const& item_policies::set(
object const& target
, object const& key
, object const& value)
{
python::setitem(target, key, value);
return value;
}
}
namespace converter
{
// These specializations are a lie; the proxies do not directly
// manage an object. What actually happens is that the implicit
// conversion to object takes hold and its conversion to_python is
// used. That's OK in part because the object temporary *is*
// actually managing the object during the duration of the
// conversion.
template <>
struct is_object_manager<object_item>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <>
struct is_object_manager<const_object_item>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
}
}} // namespace boost::python
#endif // OBJECT_ITEMS_DWA2002615_HPP

View File

@@ -0,0 +1,45 @@
// 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 OBJECT_PROTOCOL_DWA2002615_HPP
# define OBJECT_PROTOCOL_DWA2002615_HPP
# include <boost/python/detail/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/object_protocol_core.hpp>
# include <boost/python/object_core.hpp>
namespace boost { namespace python {
template <class Target, class Key>
inline object getattr(Target const& target, Key const& key)
{
return getattr(object(target), object(key));
}
template <class Key, class Value>
inline void setattr(object const& target, Key const& key, Value const& value)
{
return setattr(target, object(key), object(value));
}
template <class Target, class Key>
inline object getitem(Target const& target, Key const& key)
{
return getitem(object(target), object(key));
}
template <class Key, class Value>
inline void setitem(object const& target, Key const& key, Value const& value)
{
return setitem(target, object(key), object(value));
}
}} // namespace boost::python
#endif // OBJECT_PROTOCOL_DWA2002615_HPP

View File

@@ -0,0 +1,20 @@
// 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 OBJECT_PROTOCOL_CORE_DWA2002615_HPP
# define OBJECT_PROTOCOL_CORE_DWA2002615_HPP
namespace boost { namespace python {
class object;
BOOST_PYTHON_DECL object getattr(object const& target, object const& key);
BOOST_PYTHON_DECL void setattr(object const& target, object const& key, object const& value);
BOOST_PYTHON_DECL object getitem(object const& target, object const& key);
BOOST_PYTHON_DECL void setitem(object const& target, object const& key, object const& value);
}} // namespace boost::python
#endif // OBJECT_PROTOCOL_CORE_DWA2002615_HPP

View File

@@ -0,0 +1,101 @@
// 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 OBJECT_CALL_DWA2002612_HPP
# define OBJECT_CALL_DWA2002612_HPP
template<class A0>
object
operator()(A0 const&a0)const
{
return call<object>(&**this,a0);
}
template<class A0,class A1>
object
operator()(A0 const&a0,A1 const&a1)const
{
return call<object>(&**this,a0,a1);
}
template<class A0,class A1,class A2>
object
operator()(A0 const&a0,A1 const&a1,A2 const&a2)const
{
return call<object>(&**this,a0,a1,a2);
}
template<class A0,class A1,class A2,class A3>
object
operator()(A0 const&a0,A1 const&a1,A2 const&a2,A3 const&a3)const
{
return call<object>(&**this,a0,a1,a2,a3);
}
template<class A0,class A1,class A2,class A3,class A4>
object
operator()(A0 const&a0,A1 const&a1,A2 const&a2,A3 const&a3,A4 const&a4)const
{
return call<object>(&**this,a0,a1,a2,a3,a4);
}
template<class A0,class A1,class A2,class A3,class A4,class A5>
object
operator()(A0 const&a0,A1 const&a1,A2 const&a2,A3 const&a3,A4 const&a4,A5 const&a5)const
{
return call<object>(&**this,a0,a1,a2,a3,a4,a5);
}
template<class A0,class A1,class A2,class A3,class A4,class A5,class A6>
object
operator()(A0 const&a0,A1 const&a1,A2 const&a2,A3 const&a3,A4 const&a4,A5 const&a5,A6 const&a6)const
{
return call<object>(&**this,a0,a1,a2,a3,a4,a5,a6);
}
template<class A0,class A1,class A2,class A3,class A4,class A5,class A6,class A7>
object
operator()(A0 const&a0,A1 const&a1,A2 const&a2,A3 const&a3,A4 const&a4,A5 const&a5,A6 const&a6,A7 const&a7)const
{
return call<object>(&**this,a0,a1,a2,a3,a4,a5,a6,a7);
}
template<class A0,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8>
object
operator()(A0 const&a0,A1 const&a1,A2 const&a2,A3 const&a3,A4 const&a4,A5 const&a5,A6 const&a6,A7 const&a7,A8 const&a8)const
{
return call<object>(&**this,a0,a1,a2,a3,a4,a5,a6,a7,a8);
}
template<class A0,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9>
object
operator()(A0 const&a0,A1 const&a1,A2 const&a2,A3 const&a3,A4 const&a4,A5 const&a5,A6 const&a6,A7 const&a7,A8 const&a8,A9 const&a9)const
{
return call<object>(&**this,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9);
}
template<class A0,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9,class A10>
object
operator()(A0 const&a0,A1 const&a1,A2 const&a2,A3 const&a3,A4 const&a4,A5 const&a5,A6 const&a6,A7 const&a7,A8 const&a8,A9 const&a9,A10 const&a10)const
{
return call<object>(&**this,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10);
}
template<class A0,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9,class A10,class A11>
object
operator()(A0 const&a0,A1 const&a1,A2 const&a2,A3 const&a3,A4 const&a4,A5 const&a5,A6 const&a6,A7 const&a7,A8 const&a8,A9 const&a9,A10 const&a10,A11 const&a11)const
{
return call<object>(&**this,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11);
}
template<class A0,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9,class A10,class A11,class A12>
object
operator()(A0 const&a0,A1 const&a1,A2 const&a2,A3 const&a3,A4 const&a4,A5 const&a5,A6 const&a6,A7 const&a7,A8 const&a8,A9 const&a9,A10 const&a10,A11 const&a11,A12 const&a12)const
{
return call<object>(&**this,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12);
}
template<class A0,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9,class A10,class A11,class A12,class A13>
object
operator()(A0 const&a0,A1 const&a1,A2 const&a2,A3 const&a3,A4 const&a4,A5 const&a5,A6 const&a6,A7 const&a7,A8 const&a8,A9 const&a9,A10 const&a10,A11 const&a11,A12 const&a12,A13 const&a13)const
{
return call<object>(&**this,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13);
}
template<class A0,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9,class A10,class A11,class A12,class A13,class A14>
object
operator()(A0 const&a0,A1 const&a1,A2 const&a2,A3 const&a3,A4 const&a4,A5 const&a5,A6 const&a6,A7 const&a7,A8 const&a8,A9 const&a9,A10 const&a10,A11 const&a11,A12 const&a12,A13 const&a13,A14 const&a14)const
{
return call<object>(&**this,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14);
}
#endif // OBJECT_CALL_DWA2002612_HPP

129
include/boost/python/proxy.hpp Executable file
View File

@@ -0,0 +1,129 @@
// 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 PROXY_DWA2002615_HPP
# define PROXY_DWA2002615_HPP
# include <boost/python/object_core.hpp>
namespace boost { namespace python {
class object;
template <class Policies>
class proxy
{
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200
typedef proxy const& copy_ctor_self;
# else
typedef proxy copy_ctor_self;
# endif
public:
operator object() const;
// to support a[b] = c[d]
proxy& operator=(copy_ctor_self);
template <class T>
inline proxy& operator=(T const& rhs)
{
Policies::set(m_target, m_key, python::object(rhs));
return *this;
}
# define BOOST_PYTHON_PROXY_ASSIGN_DECL(op) \
object operator op (object const&); \
\
template <class T> \
object operator op (T const& rhs) \
{ \
return *this op python::object(rhs); \
}
// BOOST_PYTHON_PROXY_ASSIGN_DECL(=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(+=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(-=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(*=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(/=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(%=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(<<=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(>>=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(&=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(^=)
BOOST_PYTHON_PROXY_ASSIGN_DECL(|=)
# undef BOOST_PYTHON_PROXY_ASSIGN_DECL
// truth value testing
operator object::bool_type() const;
bool operator!() const; // needed for vc6
private:
friend class object;
proxy(object const& target, object const& key);
private:
object m_target;
object m_key;
};
//
// implementation
//
template <class Policies>
inline proxy<Policies>::proxy(object const& target, object const& key)
: m_target(target), m_key(key)
{}
template <class Policies>
inline proxy<Policies>::operator object() const
{
return Policies::get(m_target, m_key);
}
// to support a[b] = c[d]
template <class Policies>
inline proxy<Policies>& proxy<Policies>::operator=(typename proxy::copy_ctor_self rhs)
{
return *this = python::object(rhs);
}
# define BOOST_PYTHON_PROXY_ASSIGN_DEF(op) \
template <class Policies> \
inline object proxy<Policies>::operator op(object const& other) \
{ \
return Policies::set( \
m_target, m_key \
, Policies::get(m_target,m_key) op other); \
}
BOOST_PYTHON_PROXY_ASSIGN_DEF(+=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(-=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(*=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(/=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(%=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(<<=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(>>=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(&=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(^=)
BOOST_PYTHON_PROXY_ASSIGN_DEF(|=)
# undef BOOST_PYTHON_PROXY_ASSIGN_DEF
template <class Policies>
inline proxy<Policies>::operator object::bool_type() const
{
return python::object(*this);
}
template <class Policies>
inline bool proxy<Policies>::operator!() const
{
return !python::object(*this);
}
}} // namespace boost::python
#endif // PROXY_DWA2002615_HPP

View File

@@ -0,0 +1,42 @@
// 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 REFCOUNT_DWA2002615_HPP
# define REFCOUNT_DWA2002615_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/cast.hpp>
namespace boost { namespace python {
template <class T>
inline T* incref(T* p)
{
Py_INCREF(python::upcast<PyObject>(p));
return p;
}
template <class T>
inline T* xincref(T* p)
{
Py_XINCREF(python::upcast<PyObject>(p));
return p;
}
template <class T>
inline void decref(T* p)
{
Py_DECREF(python::upcast<PyObject>(p));
}
template <class T>
inline void xdecref(T* p)
{
Py_XDECREF(python::upcast<PyObject>(p));
}
}} // namespace boost::python
#endif // REFCOUNT_DWA2002615_HPP

View File

@@ -10,34 +10,84 @@
# include <boost/python/converter/registry.hpp>
# include <boost/python/converter/to_python_function.hpp>
# include <boost/python/converter/builtin_converters.hpp>
# include <boost/python/converter/object_manager.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/type_traits/ice.hpp>
# include <boost/python/refcount.hpp>
namespace boost { namespace python {
template <class T>
struct to_python_value
namespace detail
{
typedef typename add_reference<
typename add_const<T>::type
>::type argument_type;
template <class T>
struct object_manager_to_python_value
{
typedef typename add_reference<
typename add_const<T>::type
>::type argument_type;
static bool convertible();
PyObject* operator()(argument_type) const;
};
static bool convertible();
PyObject* operator()(argument_type) const;
};
template <class T>
bool to_python_value<T>::convertible()
{
// if this assert fires, our static variable hasn't been set up yet.
return converter::to_python_function<argument_type>::value != 0;
template <class T>
struct registry_to_python_value
{
typedef typename add_reference<
typename add_const<T>::type
>::type argument_type;
static bool convertible();
PyObject* operator()(argument_type) const;
};
}
template <class T>
PyObject* to_python_value<T>::operator()(argument_type x) const
struct to_python_value
: mpl::select_type<
boost::type_traits::ice_or<
converter::is_object_manager<T>::value
, converter::is_reference_to_object_manager<T>::value
>::value
, detail::object_manager_to_python_value<T>
, detail::registry_to_python_value<T>
>::type
{
// This might be further optimized on platforms which dynamically
// link without specific imports/exports
return converter::to_python_function<argument_type>::value(&x);
};
//
// implementation
//
namespace detail
{
template <class T>
inline bool registry_to_python_value<T>::convertible()
{
return converter::to_python_function<argument_type>::value != 0;
}
template <class T>
inline PyObject* registry_to_python_value<T>::operator()(argument_type x) const
{
return converter::to_python_function<argument_type>::value(&x);
}
template <class T>
inline bool object_manager_to_python_value<T>::convertible()
{
return true;
}
template <class T>
inline PyObject* object_manager_to_python_value<T>::operator()(argument_type x) const
{
return python::upcast<PyObject>(
python::xincref(
converter::get_managed_object(x))
);
}
}
}} // namespace boost::python

View File

@@ -35,7 +35,11 @@ namespace detail
arg_to_python_base::arg_to_python_base(
void const volatile* source, to_python_function_t converter)
# if !defined(BOOST_MSVC) || _MSC_FULL_VER != 13102140
: handle<>(convert(source, converter))
# else
: m_ptr(convert(source, converter))
# endif
{
}

View File

@@ -14,7 +14,7 @@ namespace boost { namespace python { namespace detail {
module_base::module_base(const char* name)
: m_module(
borrow(Py_InitModule(const_cast<char*>(name), initial_methods))
python::borrowed(Py_InitModule(const_cast<char*>(name), initial_methods))
)
{
}

View File

@@ -110,7 +110,7 @@ namespace objects
if (PyType_Ready(&class_metatype_object))
return type_handle();
}
return type_handle(borrow(&class_metatype_object));
return type_handle(borrowed(&class_metatype_object));
}
extern "C"
{
@@ -181,7 +181,7 @@ namespace objects
if (PyType_Ready(&class_type_object))
return type_handle();
}
return type_handle(borrow(&class_type_object));
return type_handle(borrowed(&class_type_object));
}
BOOST_PYTHON_DECL void*

35
src/object_protocol.cpp Executable file
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.
#include <boost/python/object_protocol.hpp>
#include <boost/python/errors.hpp>
#include <boost/python/object.hpp>
namespace boost { namespace python {
object getattr(object const& target, object const& key)
{
return object((object::new_pyobject_reference*)PyObject_GetAttr(&*target, &*key));
}
void setattr(object const& target, object const& key, object const& value)
{
if (PyObject_SetAttr(&*target, &*key, &*value) == -1)
throw_error_already_set();
}
object getitem(object const& target, object const& key)
{
return object((object::new_pyobject_reference*)PyObject_GetItem(&*target, &*key));
}
void setitem(object const& target, object const& key, object const& value)
{
if (PyObject_SetItem(&*target, &*key, &*value) == -1)
throw_error_already_set();
}
}} // namespace boost::python

View File

@@ -18,7 +18,7 @@
namespace boost { namespace python {
objects_base::objects_base(handle<> const& p)
: m_p(borrow(p.get())) // Do the null check here
: m_p(borrowed(p.get())) // Do the null check here
{}
// Return a reference to the held object
@@ -72,7 +72,7 @@ std::size_t tuple_base::size() const
handle<> tuple_base::operator[](std::size_t pos) const
{
return handle<>(borrow(PyTuple_GetItem(get(), static_cast<int>(pos))));
return handle<>(borrowed(PyTuple_GetItem(get(), static_cast<int>(pos))));
}
void tuple_base::set_item(std::size_t pos, const handle<>& rhs)
@@ -146,7 +146,7 @@ const char* string::c_str() const
void string::intern()
{ // UNTESTED!!
*this = string(handle<>(borrow(PyString_InternFromString(c_str()))));
*this = string(handle<>(borrowed(PyString_InternFromString(c_str()))));
}
string& string::operator*=(unsigned int repeat_count)
@@ -214,7 +214,7 @@ handle<> dictionary_base::get_item(const handle<>& key, const handle<>& default_
if (value_or_null == 0 && !PyErr_Occurred())
return default_;
else
return handle<>(borrow(value_or_null)); // Will throw if there was another error
return handle<>(borrowed(value_or_null)); // Will throw if there was another error
}
void dictionary_base::set_item(const handle<>& key, const handle<>& value)
@@ -310,7 +310,7 @@ std::size_t list_base::size() const
handle<> list_base::operator[](std::size_t pos) const
{
return handle<>(borrow(PyList_GetItem(get(), pos)));
return handle<>(borrowed(PyList_GetItem(get(), pos)));
}
list_proxy list_base::operator[](std::size_t pos)
@@ -370,12 +370,12 @@ const handle<>& list_proxy::operator=(const handle<>& rhs)
list_proxy::operator handle<>() const
{
return handle<>(borrow(PyList_GetItem(m_list.get(), m_index)));
return handle<>(borrowed(PyList_GetItem(m_list.get(), m_index)));
}
handle<> list_base::get_item(std::size_t pos) const
{
return handle<>(borrow(PyList_GetItem(this->get(), pos)));
return handle<>(borrowed(PyList_GetItem(this->get(), pos)));
}
void list_base::set_item(std::size_t pos, const handle<>& rhs)

View File

@@ -1,8 +1,11 @@
subproject libs/python/test ;
# bring in the rules for python
SEARCH on <module@>python.jam = $(BOOST_BUILD_PATH) ;
include <module@>python.jam ;
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
include python.jam ;
# bring in rules for testing
SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
include testing.jam ;
local PYTHON_V1_PROPERTIES = $(PYTHON_PROPERTIES) ;
local PYTHON_PROPERTIES = $(BOOST_PYTHON_V2_PROPERTIES) ;
@@ -58,6 +61,7 @@ bpl-test builtin_converters : test_builtin_converters.py test_builtin_converters
bpl-test test_pointer_adoption ;
bpl-test operators ;
bpl-test callbacks ;
bpl-test object ;
bpl-test virtual_functions ;
bpl-test back_reference ;
bpl-test implicit ;
@@ -76,44 +80,44 @@ if $(TEST_BIENSTMAN_NON_BUGS)
}
# --- unit tests of library components ---
unit-test indirect_traits_test
: indirect_traits_test.cpp : <sysinclude>$(BOOST_ROOT) ;
unit-test destroy_test
: destroy_test.cpp : <sysinclude>$(BOOST_ROOT) ;
unit-test pointer_type_id_test
: pointer_type_id_test.cpp : <sysinclude>$(BOOST_ROOT) ;
run indirect_traits_test.cpp ;
run destroy_test.cpp ;
run pointer_type_id_test.cpp ;
run member_function_cast.cpp ;
run bases.cpp ;
run if_else.cpp ;
run pointee.cpp ;
run result.cpp ;
compile borrowed.cpp : $(PYTHON_PROPERTIES) ;
compile object_manager.cpp : $(PYTHON_PROPERTIES) ;
unit-test member_function_cast
: member_function_cast.cpp : <sysinclude>$(BOOST_ROOT) ;
run upcast.cpp
: # command-line args
: # input files
: [ difference $(PYTHON_PROPERTIES) : <define>BOOST_PYTHON_DYNAMIC_LIB ]
<define>BOOST_PYTHON_STATIC_LIB
;
unit-test bases
: bases.cpp : <sysinclude>$(BOOST_ROOT) ;
unit-test if_else
: if_else.cpp : <sysinclude>$(BOOST_ROOT) ;
unit-test pointee
: pointee.cpp : <sysinclude>$(BOOST_ROOT) ;
unit-test result
: result.cpp : <sysinclude>$(BOOST_ROOT) ;
unit-test upcast
: upcast.cpp
: <sysinclude>$(BOOST_ROOT) <define>BOOST_PYTHON_STATIC_LIB $(PYTHON_PROPERTIES) ;
unit-test select_holder
: select_holder.cpp
: <sysinclude>$(BOOST_ROOT) <define>BOOST_PYTHON_STATIC_LIB $(PYTHON_PROPERTIES)
;
unit-test select_from_python_test
: select_from_python_test.cpp
../src/converter/type_id.cpp
: <sysinclude>$(BOOST_ROOT)
[ difference $(PYTHON_PROPERTIES) : <define>BOOST_PYTHON_DYNAMIC_LIB ]
run select_holder.cpp
: # command-line args
: # input files
: [ difference $(PYTHON_PROPERTIES) : <define>BOOST_PYTHON_DYNAMIC_LIB ]
<define>BOOST_PYTHON_STATIC_LIB
;
run select_from_python_test.cpp ../src/converter/type_id.cpp
: # command-line args
: # input files
: [ difference $(PYTHON_PROPERTIES) : <define>BOOST_PYTHON_DYNAMIC_LIB ]
<define>BOOST_PYTHON_STATIC_LIB
;
if $(TEST_EXPECTED_FAILURES)
{
compile-fail ./raw_pyobject_fail1.cpp : $(PYTHON_PROPERTIES) ;
compile-fail ./raw_pyobject_fail2.cpp : $(PYTHON_PROPERTIES) ;
compile-fail ./object_fail1.cpp : $(PYTHON_PROPERTIES) ;
}

33
test/borrowed.cpp Executable file
View File

@@ -0,0 +1,33 @@
// 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.
#include <boost/python/borrowed.hpp>
#include <boost/static_assert.hpp>
using namespace boost::python;
template <class T>
void assert_borrowed_ptr(T const& x)
{
BOOST_STATIC_ASSERT(boost::python::detail::is_borrowed_ptr<T>::value);
}
template <class T>
void assert_not_borrowed_ptr(T const& x)
{
BOOST_STATIC_ASSERT(!boost::python::detail::is_borrowed_ptr<T>::value);
}
int main()
{
assert_borrowed_ptr(borrowed((PyObject*)0));
assert_borrowed_ptr(borrowed((PyTypeObject*)0));
assert_borrowed_ptr((detail::borrowed<PyObject> const*)0);
assert_borrowed_ptr((detail::borrowed<PyObject> volatile*)0);
assert_borrowed_ptr((detail::borrowed<PyObject> const volatile*)0);
assert_not_borrowed_ptr((PyObject*)0);
assert_not_borrowed_ptr(0);
return 0;
}

View File

@@ -11,6 +11,7 @@
#include <boost/python/return_value_policy.hpp>
#include <boost/python/reference_existing_object.hpp>
#include <boost/python/call.hpp>
#include <boost/python/object.hpp>
using namespace boost::python;
@@ -51,12 +52,12 @@ void apply_void_X_ref(PyObject* f, X& x)
call<void>(f, boost::ref(x));
}
X& apply_X_ref_pyobject(PyObject* f, PyObject* obj)
X& apply_X_ref_handle(PyObject* f, handle<> obj)
{
return call<X&>(f, obj);
}
X* apply_X_ptr_pyobject(PyObject* f, PyObject* obj)
X* apply_X_ptr_handle_cref(PyObject* f, handle<> const& obj)
{
return call<X*>(f, obj);
}
@@ -83,7 +84,7 @@ char const* apply_cstring_cstring(PyObject* f, char const* s)
char const* apply_cstring_pyobject(PyObject* f, PyObject* s)
{
return call<char const*>(f, s);
return call<char const*>(f, borrowed(s));
}
char apply_char_char(PyObject* f, char c)
@@ -96,11 +97,25 @@ char const* apply_to_string_literal(PyObject* f)
return call<char const*>(f, "hello, world");
}
handle<> apply_to_own_type(handle<> x)
{
// Tests that we can return handle<> from a callback and that we
// can pass arbitrary handle<T>.
return call<handle<> >(x.get(), type_handle(borrowed(x->ob_type)));
}
object apply_object_object(PyObject* f, object x)
{
return call<object>(f, x);
}
int X::counter;
BOOST_PYTHON_MODULE_INIT(callbacks_ext)
{
boost::python::module("callbacks_ext")
.def("apply_object_object", apply_object_object)
.def("apply_to_own_type", apply_to_own_type)
.def("apply_int_int", apply_int_int)
.def("apply_void_int", apply_void_int)
.def("apply_X_X", apply_X_X)
@@ -109,10 +124,10 @@ BOOST_PYTHON_MODULE_INIT(callbacks_ext)
.def("apply_void_X_ptr", apply_void_X_ptr)
.def("apply_void_X_deep_ptr", apply_void_X_deep_ptr)
.def("apply_X_ptr_pyobject", apply_X_ptr_pyobject
.def("apply_X_ptr_handle_cref", apply_X_ptr_handle_cref
, return_value_policy<reference_existing_object>())
.def("apply_X_ref_pyobject", apply_X_ref_pyobject
.def("apply_X_ref_handle", apply_X_ref_handle
, return_value_policy<reference_existing_object>())
.def("apply_cstring_cstring", apply_cstring_cstring)

View File

@@ -74,27 +74,27 @@ succeed<wink>:
>>> last_x.value()
43
>>> y = apply_X_ref_pyobject(identity, x)
>>> y = apply_X_ref_handle(identity, x)
>>> assert y.value() == x.value()
>>> increment(x)
>>> assert y.value() == x.value()
>>> y = apply_X_ptr_pyobject(identity, x)
>>> y = apply_X_ptr_handle_cref(identity, x)
>>> assert y.value() == x.value()
>>> increment(x)
>>> assert y.value() == x.value()
>>> y = apply_X_ptr_pyobject(identity, None)
>>> y = apply_X_ptr_handle_cref(identity, None)
>>> y
>>> def new_x(ignored):
... return X(666)
...
>>> try: apply_X_ref_pyobject(new_x, 1)
>>> try: apply_X_ref_handle(new_x, 1)
... except ReferenceError: pass
... else: print 'no error'
>>> try: apply_X_ptr_pyobject(new_x, 1)
>>> try: apply_X_ptr_handle_cref(new_x, 1)
... except ReferenceError: pass
... else: print 'no error'
@@ -113,6 +113,10 @@ succeed<wink>:
>>> apply_char_char(identity, 'x')
'x'
>>> assert apply_to_own_type(identity) is type(identity)
>>> assert apply_object_object(identity, identity) is identity
'''
def run(args = None):

149
test/object.cpp Executable file
View File

@@ -0,0 +1,149 @@
// 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.
#include <boost/python/module.hpp>
#include <boost/python/object.hpp>
using namespace boost::python;
object call_object_3(object f)
{
return f(3);
}
object message()
{
return object("hello, world!");
}
object number()
{
return object(42);
}
object obj_getattr(object x, char const* name)
{
return x._(name);
}
object obj_const_getattr(object const& x, char const* name)
{
return x._(name);
}
void obj_setattr(object x, char const* name, object value)
{
x._(name) = value;
}
void obj_setattr42(object x, char const* name)
{
x._(name) = 42;
}
void obj_moveattr(object& x, char const* src, char const* dst)
{
x._(dst) = x._(src);
}
object obj_getitem(object x, object key)
{
return x[key];
}
object obj_getitem3(object x)
{
return x[3];
}
object obj_const_getitem(object const& x, object key)
{
return x[key];
}
void obj_setitem(object x, object key, object value)
{
x[key] = value;
}
void obj_setitem42(object x, object key)
{
x[key] = 42;
}
void obj_moveitem(object& x, object src, object dst)
{
x[dst] = x[src];
}
void obj_moveitem2(object const& x_src, object k_src, object& x_dst, object k_dst)
{
x_dst[k_dst] = x_src[k_src];
}
bool test(object y)
{
return y;
}
bool test_not(object y)
{
return !y;
}
bool test_attr(object y, char* name)
{
return y._(name);
}
bool test_not_attr(object y, char* name)
{
return !y._(name);
}
bool test_item(object y, object key)
{
return y[key];
}
bool test_not_item(object y, object key)
{
return !y[key];
}
BOOST_PYTHON_MODULE_INIT(object_ext)
{
module("object_ext")
.def("call_object_3", call_object_3)
.def("message", message)
.def("number", number)
.def("obj_getattr", obj_getattr)
.def("obj_const_getattr", obj_const_getattr)
.def("obj_setattr", obj_setattr)
.def("obj_setattr42", obj_setattr42)
.def("obj_moveattr", obj_moveattr)
.def("obj_getitem", obj_getitem)
.def("obj_getitem3", obj_getitem)
.def("obj_const_getitem", obj_const_getitem)
.def("obj_setitem", obj_setitem)
.def("obj_setitem42", obj_setitem42)
.def("obj_moveitem", obj_moveitem)
.def("obj_moveitem2", obj_moveitem2)
.def("test", test)
.def("test_not", test_not)
.def("test_attr", test_attr)
.def("test_not_attr", test_not_attr)
.def("test_item", test_item)
.def("test_not_item", test_not_item)
;
}
#include "module_tail.cpp"

95
test/object.py Normal file
View File

@@ -0,0 +1,95 @@
'''
>>> from object_ext import *
>>> def print1(x):
... print x
>>> call_object_3(print1)
3
>>> message()
'hello, world!'
>>> number()
42
>>> test('hi')
1
>>> test(None)
0
>>> test_not('hi')
0
>>> test_not(0)
1
Attributes
>>> class X: pass
...
>>> x = X()
>>> try: obj_getattr(x, 'foo')
... except AttributeError: pass
... else: print 'expected an exception'
>>> obj_setattr(x, 'foo', 1)
>>> x.foo
1
>>> obj_getattr(x, 'foo')
1
>>> obj_const_getattr(x, 'foo')
1
>>> obj_setattr42(x, 'foo')
>>> x.foo
42
>>> obj_moveattr(x, 'foo', 'bar')
>>> x.bar
42
>>> test_attr(x, 'foo')
1
>>> test_not_attr(x, 'foo')
0
>>> x.foo = None
>>> test_attr(x, 'foo')
0
>>> test_not_attr(x, 'foo')
1
Items
>>> d = {}
>>> obj_setitem(d, 'foo', 1)
>>> d['foo']
1
>>> obj_getitem(d, 'foo')
1
>>> obj_const_getitem(d, 'foo')
1
>>> obj_setitem42(d, 'foo')
>>> d['foo']
42
>>> obj_moveitem(d, 'foo', 'bar')
>>> d['bar']
42
>>> obj_moveitem2(d, 'bar', d, 'baz')
>>> d['baz']
42
>>> test_item(d, 'foo')
1
>>> test_not_item(d, 'foo')
0
>>> d['foo'] = None
>>> test_item(d, 'foo')
0
>>> test_not_item(d, 'foo')
1
'''
def run(args = None):
import sys
import doctest
if args is not None:
sys.argv = args
return doctest.testmod(sys.modules.get(__name__))
if __name__ == '__main__':
print "running..."
import sys
sys.exit(run()[0])

12
test/object_fail1.cpp Executable file
View File

@@ -0,0 +1,12 @@
// 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.
#include <boost/python/object.hpp>
int f(boost::python::object const& x)
{
x._("hello") = 1;
return 0;
}

37
test/object_manager.cpp Executable file
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.
#include <boost/python/converter/object_manager.hpp>
#include <boost/python/borrowed.hpp>
#include <boost/static_assert.hpp>
#include "test_class.hpp"
using namespace boost::python;
using namespace boost::python::converter;
template <class T> struct undefined;
int main()
{
BOOST_STATIC_ASSERT(is_object_manager<handle<> >::value);
BOOST_STATIC_ASSERT(!is_object_manager<int>::value);
BOOST_STATIC_ASSERT(!is_object_manager<test_class<> >::value);
BOOST_STATIC_ASSERT(is_reference_to_object_manager<handle<>&>::value);
BOOST_STATIC_ASSERT(is_reference_to_object_manager<handle<> const&>::value);
BOOST_STATIC_ASSERT(is_reference_to_object_manager<handle<> volatile&>::value);
BOOST_STATIC_ASSERT(is_reference_to_object_manager<handle<> const volatile&>::value);
// undefined<is_reference_to_object_manager<handle<> >::t1> x1;
// undefined<is_reference_to_object_manager<handle<> >::t2> x2;
BOOST_STATIC_ASSERT(!is_reference_to_object_manager<handle<> >::value);
BOOST_STATIC_ASSERT(!is_reference_to_object_manager<test_class<> >::value);
BOOST_STATIC_ASSERT(!is_reference_to_object_manager<test_class<>&>::value);
BOOST_STATIC_ASSERT(!is_reference_to_object_manager<test_class<>const&>::value);
return 0;
}

12
test/raw_pyobject_fail1.cpp Executable file
View File

@@ -0,0 +1,12 @@
// 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.
#include <boost/python/converter/arg_to_python.hpp>
int main()
{
boost::python::converter::arg_to_python<PyTypeObject*> x(0);
return 0;
}

14
test/raw_pyobject_fail2.cpp Executable file
View File

@@ -0,0 +1,14 @@
// 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.
#include <boost/python/converter/arg_to_python.hpp>
struct X : PyObject {};
int main()
{
boost::python::converter::arg_to_python<X*> x(0);
return 0;
}

View File

@@ -6,6 +6,9 @@
#include <string>
#include <boost/python/module.hpp>
#include <complex>
#include <boost/python/handle.hpp>
#include <boost/python/cast.hpp>
#include <boost/python/object.hpp>
template <class T>
struct by_value
@@ -25,11 +28,37 @@ struct by_const_reference
}
};
template <class T>
struct by_reference
{
static T rewrap(T& x)
{
return x;
}
};
using boost::python::handle;
using boost::python::object;
using boost::python::borrowed;
// Used to test that arbitrary handle<>s can be returned
handle<PyTypeObject> get_type(handle<> x)
{
return handle<PyTypeObject>(borrowed(x->ob_type));
}
handle<> return_null_handle()
{
return handle<>();
}
char const* rewrap_value_mutable_cstring(char* x) { return x; }
BOOST_PYTHON_MODULE_INIT(builtin_converters)
{
boost::python::module("builtin_converters")
.def("get_type", get_type)
.def("return_null_handle", return_null_handle)
.def("rewrap_value_bool", by_value<bool>::rewrap)
.def("rewrap_value_char", by_value<char>::rewrap)
@@ -53,6 +82,8 @@ BOOST_PYTHON_MODULE_INIT(builtin_converters)
.def("rewrap_value_complex_long_double", by_value<std::complex<long double> >::rewrap)
.def("rewrap_value_string", by_value<std::string>::rewrap)
.def("rewrap_value_cstring", by_value<char const*>::rewrap)
.def("rewrap_value_handle", by_value<handle<> >::rewrap)
.def("rewrap_value_object", by_value<object>::rewrap)
// Expose this to illustrate our failings ;-). See test_builtin_converters.py
.def("rewrap_value_mutable_cstring", rewrap_value_mutable_cstring)
@@ -80,6 +111,11 @@ BOOST_PYTHON_MODULE_INIT(builtin_converters)
.def("rewrap_const_reference_complex_long_double", by_const_reference<std::complex<long double> >::rewrap)
.def("rewrap_const_reference_string", by_const_reference<std::string>::rewrap)
.def("rewrap_const_reference_cstring", by_const_reference<char const*>::rewrap)
.def("rewrap_const_reference_handle", by_const_reference<handle<> >::rewrap)
.def("rewrap_const_reference_object", by_const_reference<object>::rewrap)
.def("rewrap_reference_object", by_reference<object>::rewrap)
;
}

View File

@@ -73,6 +73,12 @@
>>> rewrap_value_string('yo, wassup?')
'yo, wassup?'
>>> rewrap_value_handle(1)
1
>>> x = 'hi'
>>> assert rewrap_value_handle(x) is x
>>> assert rewrap_value_object(x) is x
Note that we can currently get a mutable pointer into an immutable
Python string:
@@ -134,6 +140,13 @@
>>> rewrap_const_reference_string('yo, wassup?')
'yo, wassup?'
>>> rewrap_const_reference_handle(1)
1
>>> x = 'hi'
>>> assert rewrap_const_reference_handle(x) is x
>>> assert rewrap_const_reference_object(x) is x
>>> assert rewrap_reference_object(x) is x
Check that None <==> NULL
@@ -180,6 +193,13 @@ Check that classic classes also work
>>> abs(rewrap_value_complex_double(FortyTwo()) - (4+.2j)) < .000001
1
# show that arbitrary handle<T> instantiations can be returned
>>> get_type(1) is type(1)
1
>>> try: return_null_handle()
... except: pass
... else: print 'expectd an exception'
"""
def run(args = None):