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

New conversion methods, builtin converters

----------------------------------------------------------------------

Committing in .

Modified Files:
	boost/python/reference_from_python.hpp
	boost/python/value_from_python.hpp
	boost/python/converter/body.hpp
	boost/python/converter/handle.hpp
	libs/python/src/converter/builtin_converters.cpp
	libs/python/test/m1.cpp libs/python/test/m2.cpp
Added Files:
	boost/python/converter/builtin_converters.hpp
	boost/python/converter/builtin_to_python_converters.hpp
	boost/python/converter/from_python.hpp
	boost/python/converter/from_python_data.hpp
	boost/python/converter/from_python_function.hpp
	boost/python/converter/to_python.hpp
	boost/python/converter/to_python_function.hpp
	boost/python/object/auto_ptr_generator.hpp
	boost/python/object/pointer_holder.hpp
	libs/python/src/converter/from_python.cpp
	libs/python/src/converter/to_python.cpp
	libs/python/test/test_builtin_converters.cpp
	libs/python/test/test_builtin_converters.py
Removed Files:
	boost/python/convert.hpp boost/python/converter/unwrap.hpp
	boost/python/converter/unwrapper.hpp
	boost/python/converter/wrap.hpp
	boost/python/converter/wrapper.hpp
	boost/python/object/class_unwrapper.hpp
----------------------------------------------------------------------


[SVN r12596]
This commit is contained in:
Dave Abrahams
2002-01-31 05:53:54 +00:00
parent 88a8721b89
commit 6a75fa83b5
26 changed files with 1259 additions and 661 deletions

View File

@@ -1,84 +0,0 @@
// Copyright David Abrahams 2001. 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 CONVERT_DWA20011129_HPP
# define CONVERT_DWA20011129_HPP
# include <boost/python/converter/target.hpp>
# include <boost/python/converter/source.hpp>
# include <boost/python/converter/wrap.hpp>
# include <boost/python/converter/unwrap.hpp>
namespace boost { namespace python {
namespace detail
{
template <class T>
struct converter_gen
{
typedef T value_type;
typedef typename converter::source<value_type>::type source_t;
typedef converter::wrap_<source_t> wrap_t;
typedef converter::wrap_more_<source_t> wrap_more_t;
typedef typename converter::target<value_type>::type target_t;
typedef converter::unwrap_<target_t> unwrap_t;
typedef converter::unwrap_more_<target_t> unwrap_more_t;
};
}
template <class T>
struct wrap : detail::converter_gen<T>::wrap_t
{
typedef typename detail::converter_gen<T>::wrap_t base_t;
typedef typename detail::converter_gen<T>::source_t source_t;
};
template <class T>
struct wrap_more : detail::converter_gen<T>::wrap_more_t
{
typedef typename detail::converter_gen<T>::wrap_more_t base_t;
typedef typename detail::converter_gen<T>::source_t source_t;
wrap_more(converter::handle& prev);
};
template <class T>
struct unwrap : detail::converter_gen<T>::unwrap_t
{
typedef typename detail::converter_gen<T>::unwrap_t base_t;
unwrap(PyObject*);
};
template <class T>
struct unwrap_more : detail::converter_gen<T>::unwrap_more_t
{
typedef typename detail::converter_gen<T>::unwrap_more_t base_t;
unwrap_more(PyObject*, converter::handle& prev);
};
//
// implementations
//
template <class T>
inline wrap_more<T>::wrap_more(converter::handle& prev)
: base_t(prev)
{
}
template <class T>
inline unwrap<T>::unwrap(PyObject* source)
: base_t(source)
{
}
template <class T>
inline unwrap_more<T>::unwrap_more(PyObject* source, converter::handle& prev)
: base_t(source, prev)
{
}
}} // namespace boost::python
#endif // CONVERT_DWA20011129_HPP

View File

@@ -10,8 +10,6 @@
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_DECL handle;
namespace registry
{
class entry;
@@ -23,9 +21,6 @@ struct BOOST_PYTHON_DECL body
body(type_id_t key);
virtual ~body() {}
// default implementation is a no-op
virtual void destroy_handle(handle*) const;
type_id_t key() const;
protected:

View File

@@ -0,0 +1,15 @@
// 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 BUILTIN_CONVERTERS_DWA2002124_HPP
# define BUILTIN_CONVERTERS_DWA2002124_HPP
namespace boost { namespace python { namespace converter {
void initialize_builtin_converters();
}}} // namespace boost::python::converter
#endif // BUILTIN_CONVERTERS_DWA2002124_HPP

View File

@@ -0,0 +1,75 @@
// 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 BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP
# define BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP
# include <string>
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python { namespace converter {
template <class T> struct to_python_lookup;
template <class T>
struct to_python_int
{
bool convertible() const { return true; }
PyObject* operator()(T x) const { return PyInt_FromLong(long(x)); }
};
# define BOOST_PYTHON_TO_INT(T) \
template <> struct to_python_lookup<signed T const&> : to_python_int<signed T const&> {}; \
template <> struct to_python_lookup<unsigned T const&> : to_python_int<unsigned T const&> {};
BOOST_PYTHON_TO_INT(char)
BOOST_PYTHON_TO_INT(short)
BOOST_PYTHON_TO_INT(int)
BOOST_PYTHON_TO_INT(long)
# undef BOOST_TO_PYTHON_INT
template <>
struct to_python_lookup<char const*const&>
{
bool convertible() const { return true; }
PyObject* operator()(char const* x) const { return PyString_FromString(x); }
};
template <>
struct to_python_lookup<std::string const&>
{
bool convertible() const { return true; }
PyObject* operator()(std::string const& x) const
{
return PyString_FromString(x.c_str());
}
};
template <>
struct to_python_lookup<float const&>
{
bool convertible() const { return true; }
PyObject* operator()(float x) const { return PyFloat_FromDouble(x); }
};
template <>
struct to_python_lookup<double const&>
{
bool convertible() const { return true; }
PyObject* operator()(double x) const { return PyFloat_FromDouble(x); }
};
template <>
struct to_python_lookup<long double const&>
{
bool convertible() const { return true; }
PyObject* operator()(long double x) const
{
return PyFloat_FromDouble(x);
}
};
}}} // namespace boost::python::converter
#endif // BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP

View File

@@ -0,0 +1,169 @@
// 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 FROM_PYTHON_DWA2002127_HPP
# define FROM_PYTHON_DWA2002127_HPP
# include <boost/python/detail/config.hpp>
# include <boost/python/converter/body.hpp>
# include <boost/python/converter/from_python_function.hpp>
# include <boost/python/converter/from_python_data.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/converter/registration.hpp>
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python { namespace converter {
// The type of convertibility checking functions
typedef void* (*from_python_check)(PyObject*);
typedef void (*from_python_destructor)(from_python_data&);
// forward declaration
template <class T> struct from_python_lookup;
// from_python --
// A body class representing a conversion from python to C++.
struct BOOST_PYTHON_DECL from_python_converter_base : body
{
from_python_converter_base(type_id_t, from_python_check); // registers
~from_python_converter_base(); // unregisters
// Must return non-null iff the conversion will be successful. Any
// non-null pointer is acceptable, and will be passed on to the
// convert() function, so useful data can be stored there.
inline void* convertible(PyObject*) const;
// inline type_id_t key() const;
private:
// type_id_t m_key;
from_python_check m_convertible;
};
template <class T>
struct from_python_converter : from_python_converter_base
{
public: // types
typedef typename from_python_function<T>::type conversion_function;
public: // member functions
from_python_converter(from_python_check, conversion_function, from_python_destructor = 0);
T convert(PyObject*, from_python_data&) const;
void destroy(from_python_data&) const;
private: // data members
conversion_function m_convert;
from_python_destructor m_destroy;
};
// -------------------------------------------------------------------------
//struct from_python_base
//{
//};
// A class which implements from_python with a registry lookup.
template <class T>
struct from_python_lookup // : from_python_base
{
public: // types
public: // member functions
from_python_lookup(PyObject* source);
~from_python_lookup();
bool convertible() const;
T operator()(PyObject*);
public: // functions for use by conversion implementations
// Get the converter object
from_python_converter<T> const* converter() const;
private: // data members
typedef typename from_python_intermediate_data<T>::type intermediate_t;
mutable intermediate_t m_intermediate_data;
from_python_converter<T> const* m_converter;
};
//
// implementations
//
inline void* from_python_converter_base::convertible(PyObject* o) const
{
return m_convertible(o);
}
# if 0
inline type_id_t from_python_converter_base::key() const
{
return m_key;
}
# endif
template <class T>
inline from_python_converter<T>::from_python_converter(
from_python_check checker
, conversion_function converter
, from_python_destructor destructor // = 0
)
: from_python_converter_base(type_id<T>(), checker)
, m_convert(converter)
, m_destroy(destructor)
{
}
template <class T>
inline T from_python_converter<T>::convert(PyObject* src, from_python_data& data) const
{
return this->m_convert(src, data);
}
template <class T>
inline void from_python_converter<T>::destroy(from_python_data& data) const
{
if (this->m_destroy)
{
this->m_destroy(data);
}
}
template <class T>
inline from_python_lookup<T>::from_python_lookup(PyObject* src)
: m_converter(
registration<T>::get_from_python(
src, m_intermediate_data.stage1))
{
}
template <class T>
inline from_python_lookup<T>::~from_python_lookup()
{
if (m_converter != 0)
m_converter->destroy(m_intermediate_data);
}
template <class T>
inline bool from_python_lookup<T>::convertible() const
{
return this->m_converter != 0;
}
template <class T>
inline T from_python_lookup<T>::operator()(PyObject* obj)
{
return this->m_converter->convert(obj, m_intermediate_data);
}
template <class T>
inline from_python_converter<T> const*
from_python_lookup<T>::converter() const
{
return this->m_converter;
}
}}} // namespace boost::python::converter
#endif // FROM_PYTHON_DWA2002127_HPP

View File

@@ -0,0 +1,206 @@
// 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 FROM_PYTHON_AUX_DATA_DWA2002128_HPP
# define FROM_PYTHON_AUX_DATA_DWA2002128_HPP
# include <boost/python/detail/char_array.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/type_traits/same_traits.hpp>
# include <boost/type.hpp>
// Keep these for the metaprogram which EDG is choking on.
# if !defined(__EDG__) || (__EDG_VERSION__ > 245)
# include <boost/mpl/type_list.hpp>
# include <boost/mpl/for_each.hpp>
# include <boost/type_traits/alignment_traits.hpp>
# include <boost/type_traits/composite_traits.hpp>
# endif
namespace boost { namespace python { namespace converter {
// A POD which is layout-compatible with the real intermediate data
// for all from_python conversions. There may be additional storage if
// we are converting a reference type.
struct from_python_data
{
void* stage1;
};
namespace detail
{
template <class T> struct referent_alignment;
template <class T> struct referent_size;
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T>
struct referent_alignment<T&>
{
BOOST_STATIC_CONSTANT(
std::size_t, value = alignment_of<T>::value);
};
template <class T>
struct referent_size<T&>
{
BOOST_STATIC_CONSTANT(
std::size_t, value = sizeof(T));
};
# else
template <class U>
struct alignment_chars
{
BOOST_STATIC_CONSTANT(
std::size_T, n = alignment_of<U>::value);
char elements[n + 1];
};
template <class T> struct referent_alignment
{
template <class U>
static alignment_chars<U> helper(U&);
static T t;
BOOST_STATIC_CONSTANT(
std::size_t, value = sizeof(helper(t).elements) - 1);
};
template <class T> struct referent_size
{
static T t;
BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(t));
};
# endif
struct unknown_alignment
{
void* p;
};
// EDG is too slow to handle this metaprogram :(
#if !defined(__EDG__) || (__EDG_VERSION__ > 245)
struct alignment_dummy;
template <std::size_t target_alignment>
struct best_alignment_type
{
template <class T1, class T2>
struct apply
{
BOOST_STATIC_CONSTANT(
std::size_t, align1 = alignment_of<T1>::value);
BOOST_STATIC_CONSTANT(
std::size_t, align2 = alignment_of<T2>::value);
BOOST_STATIC_CONSTANT(
bool, aligned2 = (
(align2 >= target_alignment)
& (align2 % target_alignment == 0))
);
BOOST_STATIC_CONSTANT(
bool, choose_t2 = (
aligned2 && (
is_same<T1,unknown_alignment>::value
| (align2 < alignment_of<T1>::value)
| (sizeof(T2) < sizeof(T1)))
));
typedef mpl::select_type<choose_t2, T2, T1>::type type;
};
};
typedef mpl::type_list<
char,short,int,long,float,double,long double
,void*
,void(*)()
,void (alignment_dummy::*)()
, char (alignment_dummy::*)
>
align_types;
#endif // EDG is too slow
template <class Align, std::size_t size>
struct aligned_storage
{
typedef Align align_t;
union
{
Align align;
char bytes[size
// this is just a STATIC_ASSERT. For some reason
// MSVC was barfing on the boost one.
- (is_same<align_t,unknown_alignment>::value ? size : 0)];
};
};
template <class Reference>
struct referent_storage
{
// EDG is too slow to handle this metaprogram :(
#if !defined(__EDG__) || (__EDG_VERSION__ > 245)
typedef mpl::for_each<
align_types
, unknown_alignment
, best_alignment_type<referent_alignment<Reference>::value>
> loop;
typedef typename loop::state align_t;
#else
// The Python source makes the assumption that double has
// maximal alignment anyway
typedef double align_t;
#endif
typedef aligned_storage<align_t,referent_size<Reference>::value> type;
};
template <class T>
struct intermediate_data : from_python_data
{
typename referent_storage<T>::type stage2;
};
template <>
struct intermediate_data<void> : from_python_data
{
};
}
// -------------------------------------------------------------------------
// Auxiliary POD storage where the convertible and/or convert functions of a
// from_python object may place arbitrary data.
//
// Always starts with a void*
//
// For references, we produce additional aligned storage sufficient to
// store the referent
template <class T>
struct from_python_intermediate_data
{
typedef typename mpl::select_type<
is_reference<T>::value, T, void>::type just_reference_t;
typedef detail::intermediate_data<just_reference_t> type;
};
template <class T>
void* get_storage(from_python_data& x, boost::type<T>* = 0)
{
typedef typename from_python_intermediate_data<T>::type layout;
return static_cast<layout*>(&x)->stage2.bytes;
}
}}} // namespace boost::python::converter
#endif // FROM_PYTHON_AUX_DATA_DWA2002128_HPP

View File

@@ -0,0 +1,23 @@
// 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 FROM_PYTHON_FUNCTION_DWA2002128_HPP
# define FROM_PYTHON_FUNCTION_DWA2002128_HPP
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python { namespace converter {
struct from_python_data;
template <class T>
struct from_python_function
{
typedef T (*type)(PyObject*, from_python_data&);
};
}}} // namespace boost::python::converter
#endif // FROM_PYTHON_FUNCTION_DWA2002128_HPP

View File

@@ -24,6 +24,7 @@ struct BOOST_PYTHON_DECL handle : boost::noncopyable
//
// Constructors taking a handle links this into a chain of
// handles, for more efficient management in function wrappers
handle();
handle(body* body);
handle(body* body, handle& prev);
@@ -43,6 +44,9 @@ struct BOOST_PYTHON_DECL handle : boost::noncopyable
protected: // member functions for derived classes
// Get the body we hold
inline body* get_body() const;
inline void set_body(body*);
inline void set_prev(handle&);
// Release all bodies in the chain, in reverse order of
// initialization. Only actually called for the head of the chain.
@@ -59,6 +63,10 @@ struct BOOST_PYTHON_DECL handle : boost::noncopyable
//
// implementations
//
inline handle::handle()
: m_next(0)
{}
inline handle::handle(body* body, handle& prev)
: m_body(body), m_next(0)
{
@@ -85,6 +93,16 @@ inline body* handle::get_body() const
return m_body;
}
inline void handle::set_body(body* body)
{
m_body = body;
}
inline void handle::set_prev(handle& prev)
{
prev.m_next = this;
}
}}} // namespace boost::python::converter
#endif // HANDLE_DWA20011130_HPP

View File

@@ -0,0 +1,116 @@
// 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 TO_PYTHON_DWA2002127_HPP
# define TO_PYTHON_DWA2002127_HPP
# include <boost/python/detail/config.hpp>
# include <boost/python/converter/body.hpp>
# include <boost/python/converter/registration.hpp>
# include <boost/python/converter/source_holder.hpp>
# include <boost/python/converter/to_python_function.hpp>
# include <boost/python/converter/builtin_to_python_converters.hpp>
namespace boost { namespace python { namespace converter {
template <class T> struct to_python_lookup;
struct BOOST_PYTHON_DECL to_python_converter_base : body
{
to_python_converter_base(type_id_t, to_python_function_base); // registers
~to_python_converter_base(); // unregisters
// inline type_id_t key() const;
inline to_python_function_base converter() const;
private:
// type_id_t m_key;
to_python_function_base m_convert;
};
template <class T>
struct to_python_converter : to_python_converter_base
{
public: // types
typedef typename to_python_function<T>::type converter_t;
public: // member functions
to_python_converter(converter_t);
converter_t converter() const;
private: // data members
converter_t m_convert;
};
// -------------------------------------------------------------------------
//struct to_python_base {};
template <class T>
struct to_python_lookup //: to_python_base
{
public: // member functions
to_python_lookup();
bool convertible() const;
PyObject* operator()(T) const;
private:
typename to_python_function<T>::type m_convert;
};
//
// implementations
//
# if 0
inline type_id_t
to_python_converter_base::key() const
{
return m_key;
}
# endif
inline to_python_function_base
to_python_converter_base::converter() const
{
return m_convert;
}
template <class T>
to_python_converter<T>::to_python_converter(converter_t convert)
: to_python_converter_base(
type_id<T>(), reinterpret_cast<to_python_function_base>(convert))
{
}
template <class T>
inline typename to_python_function<T>::type
to_python_converter<T>::converter() const
{
return reinterpret_cast<converter_t>(
this->to_python_converter_base::converter());
}
template <class T>
inline to_python_lookup<T>::to_python_lookup()
: m_convert(
registration<T>::get_to_python())
{
}
template <class T>
inline bool
to_python_lookup<T>::convertible() const
{
return m_converter != 0;
}
template <class T>
inline PyObject*
to_python_lookup<T>::operator()(T x) const
{
return m_convert ? m_convert(x) : 0;
}
}}} // namespace boost::python::converter
#endif // TO_PYTHON_DWA2002127_HPP

View File

@@ -0,0 +1,23 @@
// 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 TO_PYTHON_FUNCTION_DWA2002128_HPP
# define TO_PYTHON_FUNCTION_DWA2002128_HPP
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python { namespace converter {
typedef PyObject* (*to_python_function_base)(void);
template <class T>
struct to_python_function
{
typedef PyObject*(*type)(T);
};
}}} // namespace boost::python::converter
#endif // TO_PYTHON_FUNCTION_DWA2002128_HPP

View File

@@ -1,172 +0,0 @@
#error obsolete
// Copyright David Abrahams 2001. 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 UNWRAP_BASE_DWA20011130_HPP
# define UNWRAP_BASE_DWA20011130_HPP
# include <boost/python/converter/unwrapper_base.hpp>
# include <boost/python/converter/unwrapper.hpp>
# include <boost/python/converter/handle.hpp>
# include <boost/python/converter/registration.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/converter/unwrapper_select.hpp>
# include <boost/python/detail/config.hpp>
# include <boost/type.hpp>
namespace boost { namespace python { namespace converter {
template <class T> struct unwrapper;
struct BOOST_PYTHON_DECL body;
struct BOOST_PYTHON_DECL unwrap_base : handle
{
public: // member functions
inline unwrap_base(PyObject* source, std::pair<unwrapper_base*,void*>, handle& prev);
inline unwrap_base(PyObject* source, std::pair<unwrapper_base*,void*>);
inline PyObject* source() const;
inline void*& data();
protected:
inline PyObject*& source();
private: // data members
PyObject* m_source;
void* m_data;
};
// These converters will be used by the function wrappers. They don't
// manage any resources, but are instead linked into a chain which is
// managed by an instance of unwrap_ or wrap_.
template <class T>
struct unwrap_more_ : unwrap_base
{
public: // member functions
// Construction
unwrap_more_(PyObject* source, handle& prev);
// invoke the conversion or throw an exception if unsuccessful
T operator*();
protected: // constructor
// this constructor is only for the use of unwrap_
unwrap_more_(PyObject* source);
private:
typedef typename unwrapper_select<T>::type unwrapper_t;
};
// specialization for PyObject*
template <>
struct unwrap_more_<PyObject*>
: unwrap_base
{
public: // member functions
// Construction
unwrap_more_(PyObject* source, handle& prev)
: unwrap_base(source, m_unwrapper, prev)
{
}
// invoke the conversion or throw an exception if unsuccessful
PyObject* operator*()
{
return source();
}
void* can_convert(PyObject*) const
{
return &m_unwrapper;
}
protected: // constructor
// this constructor is only for the use of unwrap_
unwrap_more_(PyObject* source)
: unwrap_base(source, m_unwrapper)
{
}
private:
static BOOST_PYTHON_DECL std::pair<unwrapper_base*,void*>& m_unwrapper;
};
template <class T>
struct unwrap_ : unwrap_more_<T>
{
unwrap_(PyObject* source);
~unwrap_();
};
//
// implementations
//
inline unwrap_base::unwrap_base(
PyObject* source, std::pair<unwrapper_base*,void*> unwrapper, handle& prev)
: handle(unwrapper.first, prev)
, m_source(source)
, m_data(unwrapper.second)
{
}
inline unwrap_base::unwrap_base(PyObject* source, std::pair<unwrapper_base*,void*> unwrapper)
: handle(unwrapper.first)
, m_source(source)
, m_data(unwrapper.second)
{
}
inline void*& unwrap_base::data()
{
return m_data;
}
inline PyObject* unwrap_base::source() const
{
return m_source;
}
inline PyObject*& unwrap_base::source()
{
return m_source;
}
template <class T>
unwrap_more_<T>::unwrap_more_(PyObject* source, handle& prev)
: unwrap_base(source,
registration<T>::unwrapper(source),
prev)
{
}
template <class T>
unwrap_more_<T>::unwrap_more_(PyObject* source)
: unwrap_base(source, registration<T>::unwrapper(source))
{
}
template <class T>
inline unwrap_<T>::unwrap_(PyObject* source)
: unwrap_more_<T>(source)
{
}
template <class T>
T unwrap_more_<T>::operator*()
{
return static_cast<unwrapper<T>*>(
get_body())->convert(this->source(), this->data(), boost::type<T>());
}
template <class T>
unwrap_<T>::~unwrap_()
{
this->destroy();
}
}}} // namespace boost::python::converter
#endif // UNWRAP_BASE_DWA20011130_HPP

View File

@@ -1,40 +0,0 @@
#error obsolete
// Copyright David Abrahams 2001. 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 UNWRAPPER_DWA2001127_HPP
# define UNWRAPPER_DWA2001127_HPP
# include <boost/python/converter/unwrapper_base.hpp>
# include <boost/python/converter/unwrap.hpp>
# include <boost/python/converter/body.hpp>
# include <boost/type.hpp>
namespace boost { namespace python { namespace converter {
template <class T> struct unwrap_more_;
// Abstract base for all unwrappers of Ts
template <class T>
struct unwrapper : unwrapper_base
{
public:
unwrapper();
virtual T convert(PyObject*, void*& data, boost::type<T>) const = 0;
};
//
// implementations
//
template <class T>
unwrapper<T>::unwrapper()
: unwrapper_base(type_id<T>())
{
}
}}} // namespace boost::python::converter
#endif // UNWRAPPER_DWA2001127_HPP

View File

@@ -1,167 +0,0 @@
#error obsolete
// Copyright David Abrahams 2001. 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 WRAP_DWA2001127_HPP
# define WRAP_DWA2001127_HPP
# include <boost/python/converter/registration.hpp>
# include <boost/python/converter/handle.hpp>
# include <boost/python/converter/body.hpp>
# include <boost/python/converter/wrapper.hpp>
# include <boost/python/detail/config.hpp>
# include <boost/python/converter/source_holder.hpp>
# include <boost/python/converter/wrapper_base.hpp>
# include <cassert>
namespace boost { namespace python { namespace converter {
extern BOOST_PYTHON_DECL body& identity_wrapper;
template <class T> struct wrapper;
struct wrap_base : handle
{
public: // member functions
wrap_base(body*, handle& prev);
wrap_base(body*);
PyObject* release();
public: // accessor, really only for wrappers
PyObject*& target() const;
protected:
void hold_result(PyObject*) const;
private:
mutable PyObject* m_target;
};
template <class T>
struct wrap_more_ : wrap_base
{
protected:
typedef T source_t;
public: // member functions
wrap_more_(handle& prev);
PyObject* operator()(source_t) const;
protected: // constructor for wrap_<T>, below
wrap_more_();
private: // helper functions
static wrapper_base* lookup();
private:
friend class wrapper<T>;
};
template <class T>
struct wrap_ : wrap_more_<T>
{
typedef typename wrap_more_<T>::source_t source_t;
public: // member functions
wrap_();
~wrap_();
};
// Specialization for PyObject*
template <>
struct wrap_more_<PyObject*> : wrap_base
{
protected:
typedef PyObject* source_t;
public: // member functions
wrap_more_(handle& prev)
: wrap_base(&identity_wrapper, prev) {}
PyObject* operator()(source_t x) const { return x; }
protected: // constructor for wrap_<T>, below
wrap_more_()
: wrap_base(&identity_wrapper) {}
private:
friend class wrapper<PyObject*>;
};
//
// implementations
//
inline wrap_base::wrap_base(body* body, handle& prev)
: handle(body, prev)
, m_target(0)
{
}
inline wrap_base::wrap_base(body* body)
: handle(body),
m_target(0)
{
}
inline PyObject*& wrap_base::target() const
{
return m_target;
}
inline void wrap_base::hold_result(PyObject* p) const
{
assert(m_target == 0);
m_target = p;
}
inline PyObject* wrap_base::release()
{
PyObject* result = m_target;
m_target = 0;
return result;
}
template <class T>
inline wrapper_base* wrap_more_<T>::lookup()
{
// Find the converters registered for T and get a wrapper
// appropriate for the source object
return registration<T>::wrapper();
}
template <class T>
inline wrap_more_<T>::wrap_more_(handle& prev)
: wrap_base(lookup(), prev)
{
}
template <class T>
PyObject* wrap_more_<T>::operator()(source_t x) const
{
return static_cast<wrapper<T>*>(
this->get_body())->do_conversion(*this, source_holder<T>(x));
}
template <class T>
wrap_more_<T>::wrap_more_()
: wrap_base(lookup())
{
}
template <class T>
wrap_<T>::wrap_()
: wrap_more_<T>()
{
}
template <class T>
wrap_<T>::~wrap_()
{
this->destroy();
}
}}} // namespace boost::python::converter
#endif // WRAP_DWA2001127_HPP

View File

@@ -1,57 +0,0 @@
#error obsolete
// Copyright David Abrahams 2001. 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 WRAPPER_DWA2001127_HPP
# define WRAPPER_DWA2001127_HPP
# include <boost/python/converter/wrapper_base.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/converter/wrap.hpp>
# include <boost/python/converter/source_holder.hpp>
namespace boost { namespace python { namespace converter {
extern BOOST_PYTHON_DECL body& identity_wrapper;
template <class T>
struct wrapper : wrapper_base
{
public:
wrapper();
PyObject* do_conversion(wrap_base const&, source_holder_base const&) const;
// This does the actual conversion
virtual PyObject* convert(T source) const = 0;
};
//
// implementations
//
template <class T>
wrapper<T>::wrapper()
: wrapper_base(type_id<T>())
{
}
template <class T>
PyObject* wrapper<T>::do_conversion(wrap_base const& handle_, source_holder_base const& data_) const
{
// Casting pointers instead of references suppresses a CWPro7 bug.
wrap_more_<T> const& handle = *static_cast<wrap_more_<T> const*>(&handle_);
source_holder<T> const& data = *static_cast<source_holder<T> const*>(&data_);
if (handle.target() == 0)
{
handle.hold_result(convert(data.value));
}
return handle.target();
}
}}} // namespace boost::python::converter
#endif // WRAPPER_DWA2001127_HPP

View File

@@ -0,0 +1,23 @@
// 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 AUTO_PTR_GENERATOR_DWA2002123_HPP
# define AUTO_PTR_GENERATOR_DWA2002123_HPP
# include <memory>
namespace boost { namespace python { namespace object {
struct auto_ptr_generator
{
template <class T>
struct apply
{
typedef std::auto_ptr<T> type;
};
};
}}} // namespace boost::python::object
#endif // AUTO_PTR_GENERATOR_DWA2002123_HPP

View File

@@ -1,40 +0,0 @@
// Copyright David Abrahams 2001. 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 CLASS_UNWRAPPER_DWA20011221_HPP
# define CLASS_UNWRAPPER_DWA20011221_HPP
# include <boost/python/object/class.hpp>
# include <boost/python/converter/unwrapper.hpp>
namespace boost { namespace python { namespace objects {
template <class T>
struct class_unwrapper
{
private:
template <class Target>
struct reference_unwrapper : converter::unwrapper<Target>
{
void* can_convert(PyObject* p) const
{
return find_instance<T>(p);
}
Target convert(PyObject* p, void* data, ) const
{
return *find_instance<T>(p)->target();
}
};
reference_unwrapper<T&> m_reference;
# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
reference_unwrapper<T const&> m_const_reference;
# endif
};
}}} // namespace boost::python::objects
#endif // CLASS_UNWRAPPER_DWA20011221_HPP

View File

@@ -0,0 +1,201 @@
// Copyright David Abrahams 2001. 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 POINTER_HOLDER_DWA20011215_HPP
# define POINTER_HOLDER_DWA20011215_HPP
# include <boost/python/object/class.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/object/inheritance.hpp>
# include <boost/python/detail/eval.hpp>
# include <boost/ref.hpp>
# include <boost/type.hpp>
namespace boost { namespace python { namespace objects {
template <class Pointer, class Value>
struct pointer_holder : instance_holder
{
pointer_holder(Pointer);
// Forward construction to the held object
pointer_holder(PyObject*)
: m_p(new Value) {}
template <class A1>
pointer_holder(PyObject*, A1 a1)
: m_p(new Value(
(unwrap_reference<A1>::type&)(a1)
))
{}
template <class A1, class A2>
pointer_holder(PyObject*, A1 a1, A2 a2)
: m_p(new Value(
(unwrap_reference<A1>::type&)(a1)
, (unwrap_reference<A2>::type&)(a2)
))
{}
template <class A1, class A2, class A3>
pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3)
: m_p(new Value(
(unwrap_reference<A1>::type&)(a1)
, (unwrap_reference<A2>::type&)(a2)
, (unwrap_reference<A3>::type&)(a3)
))
{}
template <class A1, class A2, class A3, class A4>
pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4)
: m_p(new Value(
(unwrap_reference<A1>::type&)(a1)
, (unwrap_reference<A2>::type&)(a2)
, (unwrap_reference<A3>::type&)(a3)
, (unwrap_reference<A4>::type&)(a4)
))
{}
template <class A1, class A2, class A3, class A4, class A5>
pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
: m_p(new Value(
(unwrap_reference<A1>::type&)(a1)
, (unwrap_reference<A2>::type&)(a2)
, (unwrap_reference<A3>::type&)(a3)
, (unwrap_reference<A4>::type&)(a4)
, (unwrap_reference<A5>::type&)(a5)
)) {}
template <class A1, class A2, class A3, class A4, class A5, class A6>
pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
: m_p(new Value(
(unwrap_reference<A1>::type&)(a1)
, (unwrap_reference<A2>::type&)(a2)
, (unwrap_reference<A3>::type&)(a3)
, (unwrap_reference<A4>::type&)(a4)
, (unwrap_reference<A5>::type&)(a5)
, (unwrap_reference<A6>::type&)(a6)
)) {}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7>
pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
: m_p(new Value(
(unwrap_reference<A1>::type&)(a1)
, (unwrap_reference<A2>::type&)(a2)
, (unwrap_reference<A3>::type&)(a3)
, (unwrap_reference<A4>::type&)(a4)
, (unwrap_reference<A5>::type&)(a5)
, (unwrap_reference<A6>::type&)(a6)
, (unwrap_reference<A7>::type&)(a7)
))
{}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
: m_p(new Value(
(unwrap_reference<A1>::type&)(a1)
, (unwrap_reference<A2>::type&)(a2)
, (unwrap_reference<A3>::type&)(a3)
, (unwrap_reference<A4>::type&)(a4)
, (unwrap_reference<A5>::type&)(a5)
, (unwrap_reference<A6>::type&)(a6)
, (unwrap_reference<A7>::type&)(a7)
, (unwrap_reference<A8>::type&)(a8)
))
{}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
: m_p(new Value(
(unwrap_reference<A1>::type&)(a1)
, (unwrap_reference<A2>::type&)(a2)
, (unwrap_reference<A3>::type&)(a3)
, (unwrap_reference<A4>::type&)(a4)
, (unwrap_reference<A5>::type&)(a5)
, (unwrap_reference<A6>::type&)(a6)
, (unwrap_reference<A7>::type&)(a7)
, (unwrap_reference<A8>::type&)(a8)
, (unwrap_reference<A9>::type&)(a9)
))
{}
template <class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class A10>
pointer_holder(PyObject*, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10)
: m_p(new Value(
(unwrap_reference<A1>::type&)(a1)
, (unwrap_reference<A2>::type&)(a2)
, (unwrap_reference<A3>::type&)(a3)
, (unwrap_reference<A4>::type&)(a4)
, (unwrap_reference<A5>::type&)(a5)
, (unwrap_reference<A6>::type&)(a6)
, (unwrap_reference<A7>::type&)(a7)
, (unwrap_reference<A8>::type&)(a8)
, (unwrap_reference<A9>::type&)(a9)
, (unwrap_reference<A10>::type&)(a10)
))
{}
private: // required holder implementation
void* holds(converter::type_id_t);
private: // data members
Pointer m_p;
};
}}}
// back to namespace boost for this forward declaration
namespace boost
{
template <class T> class shared_ptr;
}
namespace boost { namespace python { namespace objects {
struct shared_ptr_generator
{
template <class T>
struct apply
{
typedef boost::shared_ptr<T> type;
};
};
// A generator metafunction which can be passed to make_holder
// PointerGenerator should be another generator metafunction which
// makes the appropriate (smart) pointer type to hold the argument to
// pointer_holder_generator.
template <class PointerGenerator>
struct pointer_holder_generator
{
template <class Held>
struct apply
{
typedef typename detail::eval<PointerGenerator,Held>::type pointer;
typedef pointer_holder<pointer, Held> type;
};
};
template <class Pointer, class Value>
pointer_holder<Pointer,Value>::pointer_holder(Pointer p)
: m_p(p)
{
}
template <class Pointer, class Value>
void* pointer_holder<Pointer, Value>::holds(converter::type_id_t dst_t)
{
if (dst_t == converter::type_id<Pointer>())
return &this->m_p;
converter::type_id_t src_t = converter::type_id<Value>();
return src_t == dst_t ? &*this->m_p
: find_dynamic_type(&*this->m_p, src_t, dst_t);
}
}}} // namespace boost::python::objects
#endif // POINTER_HOLDER_DWA20011215_HPP

View File

@@ -26,23 +26,28 @@ template <
PyTypeObject const* python_type
, class Value
, class PythonObject
, Value& (*extract)(PythonObject&)
, class Extract
>
struct reference_from_python : type_from_python<python_type>
struct reference_from_python
{
typedef type_from_python<python_type> convertible_t;
reference_from_python()
: m_mutable_converter(convertible, convert_mutable)
, m_const_converter(convertible, convert_const)
: m_mutable_converter(
&convertible_t::convertible, convert_mutable)
, m_const_converter(
&convertible_t::convertible, convert_const)
{}
static Value& convert_mutable(PyObject* op, converter::from_python_data&)
{
return extract(*(PythonObject*)op);
return Extract::execute(*(PythonObject*)op);
}
static Value const& convert_const(PyObject* op, converter::from_python_data&)
{
return extract(*(PythonObject*)op);
return Extract::execute(*(PythonObject*)op);
}
private:

View File

@@ -9,12 +9,27 @@
# include <boost/python/converter/from_python.hpp>
# include <boost/type_traits/object_traits.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/static_assert.hpp>
namespace boost { namespace python {
template <typename T, class Derived>
struct value_from_python
{
typedef converter::from_python_check from_python_check;
value_from_python(from_python_check convertible)
: m_converter(
convertible
, &Derived::convert
// Change this to a compile-time check later to avoid
// generating destroy function
, has_trivial_destructor<T>::value ? 0 : &Derived::destroy
)
{
}
value_from_python()
: m_converter(
&Derived::convertible
@@ -25,9 +40,6 @@ struct value_from_python
, has_trivial_destructor<T>::value ? 0 : &Derived::destroy
)
{
// Scalar types are really converted by-value; the formulation
// is much simpler.
BOOST_STATIC_ASSERT(!(is_scalar<T>::value));
}
static void* get_storage(converter::from_python_data& data)

View File

@@ -8,7 +8,8 @@
#include <boost/python/detail/wrap_python.hpp>
#include <boost/python/converter/builtin_converters.hpp>
#include <boost/python/converter/target.hpp>
#include <boost/python/converter/from_python.hpp>
#include <boost/python/value_from_python.hpp>
#include <boost/python/converter/from_python_data.hpp>
#include <boost/python/reference.hpp>
#include <boost/cast.hpp>
//#include <boost/mpl/type_list.hpp>
@@ -18,113 +19,185 @@ namespace boost { namespace python { namespace converter {
namespace
{
struct int_value_functions_base
// Only an object which we know is holding a char const* can be
// converted to one
struct convertible_to_cstring
{
static void* convertible(PyObject* obj)
static unaryfunc* execute(PyObject* obj)
{
PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
return number_methods && number_methods->nb_int
? &number_methods->nb_int : 0;
}
};
template <class T>
struct int_value_functions : int_value_functions_base
{
static T convert(PyObject* obj, from_python_data& data)
{
unaryfunc f = *static_cast<unaryfunc*>(data.stage1);
ref int_object(f(obj));
return numeric_cast<T>(PyInt_AsLong(int_object.get()));
return PyString_Check(obj) ? &obj->ob_type->tp_str : 0;
}
};
struct cstring_value_functions
struct extract_cstring
{
static void* convertible(PyObject* obj)
{
return PyString_Check(obj) ? obj : 0;
}
static char const* convert(PyObject* obj, from_python_data&)
static char const* execute(PyObject* obj)
{
return PyString_AsString(obj);
}
};
char constructed;
struct string_cref_functions
// Any object which can be converted to a Python string can also be
// converted to a C++ string, since the latter owns its bytes.
struct convertible_to_string
{
typedef std::string const& result_type;
static void* convertible(PyObject* obj)
static unaryfunc* execute(PyObject* obj)
{
return obj->ob_type->tp_str ? &obj->ob_type->tp_str : 0;
}
};
// Transform a function returning a unaryfunc* into one that returns a void*
template <class F>
struct return_void_ptr
{
static void* execute(PyObject* p) { return F::execute(p); }
};
template <
class T // The target type
, class Convertible // returns a pointer to a unaryfunc producing an object
, class TExtract // ...from which TExtract extracts T's constructor argument
>
struct tp_scalar_from_python
: from_python_converter<T>
{
private:
typedef return_void_ptr<Convertible> convertible_fn;
static std::string const& convert(
PyObject* obj, from_python_data& data)
public:
tp_scalar_from_python()
: from_python_converter<T>(
&convertible_fn::execute
, convert)
{}
static T convert(PyObject* obj, from_python_data& data)
{
ref string_object((**static_cast<reprfunc*>(data.stage1))(obj));
void* storage = get_storage<result_type>(data);
std::string* p = new (storage) std::string(PyString_AsString(string_object.get()));
unaryfunc converter = *(unaryfunc*)data.stage1;
ref converted(converter(obj));
return TExtract::execute(converted.get());
}
};
// Extract a reference to T using the functions in the source
// object's type slots
template <
class T // The target type
, class Convertible // returns a pointer to a unaryfunc producing an object
, class TExtract // ...from which TExtract extracts T's constructor argument
>
struct tp_cref_from_python
: value_from_python<T, tp_cref_from_python<T,Convertible,TExtract> >
{
private:
typedef value_from_python<T, tp_cref_from_python<T,Convertible,TExtract> > base;
public:
tp_cref_from_python()
: base(&return_void_ptr<Convertible>::execute)
{}
static T const& convert(PyObject* obj, from_python_data& data)
{
unaryfunc converter = *(unaryfunc*)data.stage1;
void* storage = get_storage(data);
ref converted(converter(obj));
T* const p = new (storage) T(TExtract::execute(converted.get()));
// note that construction is successful.
data.stage1 = &constructed;
data.stage1 = p;
return *p;
}
};
static void destroy(from_python_data& data)
struct convertible_to_int
{
static unaryfunc* execute(PyObject* obj)
{
if (data.stage1 == &constructed)
PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
if (number_methods == 0)
return 0;
// For floating types, return the float conversion slot to avoid
// creating a new object. We'll handle that in
// py_int_or_float_as_long, below
if (PyObject_TypeCheck(obj, &PyFloat_Type) && number_methods->nb_float)
return &number_methods->nb_float;
return number_methods && number_methods->nb_int
? &number_methods->nb_int : 0;
}
};
struct py_int_or_float_as_long
{
static long execute(PyObject* obj)
{
if (PyObject_TypeCheck(obj, &PyFloat_Type))
{
typedef std::string string_t;
void* storage = get_storage<result_type>(data);
((string_t*)storage)->~string_t();
return numeric_cast<long>(PyFloat_AS_DOUBLE(obj));
}
else
{
return PyInt_AS_LONG(obj);
}
}
};
template <class T, class Base>
struct rvalue_const_ref_functions : Base
struct convertible_to_double
{
static T const& convert(PyObject* obj, from_python_data& data)
static unaryfunc* execute(PyObject* obj)
{
void* storage = get_storage<T const&>(data);
T* p = new (storage) T(Base::convert(obj,data));
// note that construction is successful.
data.stage1 = &constructed;
return *p;
PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
if (number_methods == 0)
return 0;
// For integer types, return the tp_int conversion slot to avoid
// creating a new object. We'll handle that in
// py_float_or_int_as_double, below
if (PyObject_TypeCheck(obj, &PyInt_Type) && number_methods->nb_int)
return &number_methods->nb_int;
return number_methods && number_methods->nb_float
? &number_methods->nb_float : 0;
}
};
struct register_int_converters
struct py_float_or_int_as_double
{
template <class Ignored, class T>
struct apply
static double execute(PyObject* obj)
{
typedef void type;
static void execute()
if (PyObject_TypeCheck(obj, &PyInt_Type))
{
typedef int_value_functions<T> value_functions;
typedef rvalue_const_ref_functions<T,value_functions> cref_functions;
static from_python_converter<T> value_from_python(
value_functions::convertible
, value_functions::convert);
static from_python_converter<T const&> cref_from_python(
cref_functions::convertible
, cref_functions::convert);
};
};
return PyInt_AS_LONG(obj);
}
else
{
return PyFloat_AS_DOUBLE(obj);
}
}
};
}
#define REGISTER_INT_CONVERTERS(U) register_int_converters::apply<void,U>::execute()
template <class T, class Convertible, class Convert>
struct scalar_from_python
{
tp_cref_from_python<T,Convertible,Convert> cref_converter;
tp_scalar_from_python<T,Convertible,Convert> value_converter;
};
template <class T>
void register_int_converters(T* = 0)
{
static scalar_from_python<T, convertible_to_int, py_int_or_float_as_long> x;
};
}
#define REGISTER_INT_CONVERTERS(U) register_int_converters<U>()
#define REGISTER_INT_CONVERTERS2(U) REGISTER_INT_CONVERTERS(signed U); REGISTER_INT_CONVERTERS(unsigned U)
@@ -134,20 +207,21 @@ void initialize_builtin_converters()
REGISTER_INT_CONVERTERS2(short);
REGISTER_INT_CONVERTERS2(int);
REGISTER_INT_CONVERTERS2(long);
// mpl::for_each<integral_types,void,register_int_converters>::execute();
static from_python_converter<char const*> cstring_from_python(
&cstring_value_functions::convertible
, &cstring_value_functions::convert);
static scalar_from_python<
float,convertible_to_double,py_float_or_int_as_double> float_from_python;
static scalar_from_python<
double,convertible_to_double,py_float_or_int_as_double> double_from_python;
static scalar_from_python<
long double,convertible_to_double,py_float_or_int_as_double> long_double_from_python;
static scalar_from_python<
char const*, convertible_to_cstring, extract_cstring> cstring_from_python;
static from_python_converter<char const*const&> cstring_cref_from_python(
&rvalue_const_ref_functions<char const*,cstring_value_functions>::convertible
, &rvalue_const_ref_functions<char const*, cstring_value_functions>::convert);
static from_python_converter<std::string const&> string_cref_from_python(
&string_cref_functions::convertible
, &string_cref_functions::convert
, &string_cref_functions::destroy);
static tp_cref_from_python<
std::string, convertible_to_string, extract_cstring> string_from_python;
}
}}} // namespace boost::python::converter

View File

@@ -0,0 +1,27 @@
// 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/from_python.hpp>
namespace boost { namespace python { namespace converter {
from_python_converter_base::from_python_converter_base(
type_id_t type
, from_python_check checker
)
: body(type)
, m_convertible(checker)
{
registry::insert(*this);
}
from_python_converter_base::~from_python_converter_base()
{
if (can_unregister())
registry::remove(*this);
}
}}} // namespace boost::python::converter

View File

@@ -0,0 +1,24 @@
// 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/to_python.hpp>
#include <boost/python/converter/registry.hpp>
namespace boost { namespace python { namespace converter {
to_python_converter_base::to_python_converter_base(type_id_t key, to_python_function_base convert)
: body(key)
, m_convert(convert)
{
registry::insert(*this);
}
to_python_converter_base::~to_python_converter_base()
{
registry::remove(*this);
}
}}} // namespace boost::python::converter

View File

@@ -64,8 +64,11 @@ struct SimpleObject
{
PyObject_HEAD
simple x;
};
static simple& extract(SimpleObject& o) { return o.x; }
struct extract_simple_object
{
static simple& execute(SimpleObject& o) { return o.x; }
};
PyTypeObject SimpleType = {
@@ -209,12 +212,13 @@ BOOST_PYTHON_MODULE_INIT(m1)
&SimpleType
, simple
, SimpleObject
, &SimpleObject::extract
, extract_simple_object
>
unwrap_simple;
static to_python_converter<simple&> simple_ref_wrapper(simple_ref_to_python);
module m1("m1");
typedef boost::python::objects::pointer_holder_generator<

View File

@@ -49,9 +49,6 @@ PyObject* unwrap_int_const_ref(int const& x)
return PyInt_FromLong(x);
}
// MSVC6 bug workaround
template <class T> struct xxxx;
// rewrap<T> extracts a T from the argument, then converts the T back
// to a PyObject* and returns it.
template <class T>

View File

@@ -0,0 +1,65 @@
// 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 <string>
#include <boost/python/module.hpp>
#include <boost/mpl/type_list.hpp>
#include <boost/mpl/for_each.hpp>
template <class T>
struct by_value
{
static T rewrap(T x)
{
return x;
}
};
template <class T>
struct by_const_reference
{
static T rewrap(T const& x)
{
return x;
}
};
BOOST_PYTHON_MODULE_INIT(builtin_converters_ext)
{
boost::python::module("builtin_converters_ext")
.def("rewrap_value_signed_char", by_value<signed char>::rewrap)
.def("rewrap_value_unsigned_char", by_value<unsigned char>::rewrap)
.def("rewrap_value_int", by_value<int>::rewrap)
.def("rewrap_value_unsigned_int", by_value<unsigned int>::rewrap)
.def("rewrap_value_short", by_value<short>::rewrap)
.def("rewrap_value_unsigned_short", by_value<unsigned short>::rewrap)
.def("rewrap_value_long", by_value<long>::rewrap)
.def("rewrap_value_unsigned_long", by_value<unsigned long>::rewrap)
.def("rewrap_value_float", by_value<float>::rewrap)
.def("rewrap_value_double", by_value<double>::rewrap)
.def("rewrap_value_long_double", by_value<long double>::rewrap)
.def("rewrap_value_string", by_value<std::string>::rewrap)
.def("rewrap_value_cstring", by_value<char const*>::rewrap)
.def("rewrap_const_reference_signed_char", by_const_reference<signed char>::rewrap)
.def("rewrap_const_reference_unsigned_char", by_const_reference<unsigned char>::rewrap)
.def("rewrap_const_reference_int", by_const_reference<int>::rewrap)
.def("rewrap_const_reference_unsigned_int", by_const_reference<unsigned int>::rewrap)
.def("rewrap_const_reference_short", by_const_reference<short>::rewrap)
.def("rewrap_const_reference_unsigned_short", by_const_reference<unsigned short>::rewrap)
.def("rewrap_const_reference_long", by_const_reference<long>::rewrap)
.def("rewrap_const_reference_unsigned_long", by_const_reference<unsigned long>::rewrap)
.def("rewrap_const_reference_float", by_const_reference<float>::rewrap)
.def("rewrap_const_reference_double", by_const_reference<double>::rewrap)
.def("rewrap_const_reference_long_double", by_const_reference<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)
;
}

View File

@@ -0,0 +1,86 @@
"""
>>> from builtin_converters_ext import *
>>> rewrap_value_signed_char(42)
42
>>> rewrap_value_unsigned_char(42)
42
>>> rewrap_value_int(42)
42
>>> rewrap_value_unsigned_int(42)
42
>>> rewrap_value_short(42)
42
>>> rewrap_value_unsigned_short(42)
42
>>> rewrap_value_long(42)
42
>>> rewrap_value_unsigned_long(42)
42
>>> abs(rewrap_value_float(4.2) - 4.2) < .000001
1
>>> rewrap_value_double(4.2) - 4.2
0.0
>>> rewrap_value_long_double(4.2) - 4.2
0.0
>>> rewrap_value_cstring('hello, world')
'hello, world'
>>> rewrap_value_string('yo, wassup?')
'yo, wassup?'
>>> rewrap_const_reference_signed_char(42)
42
>>> rewrap_const_reference_unsigned_char(42)
42
>>> rewrap_const_reference_int(42)
42
>>> rewrap_const_reference_unsigned_int(42)
42
>>> rewrap_const_reference_short(42)
42
>>> rewrap_const_reference_unsigned_short(42)
42
>>> rewrap_const_reference_long(42)
42
>>> rewrap_const_reference_unsigned_long(42)
42
>>> abs(rewrap_const_reference_float(4.2) - 4.2) < .000001
1
>>> rewrap_const_reference_double(4.2) - 4.2
0.0
>>> rewrap_const_reference_long_double(4.2) - 4.2
0.0
>>> rewrap_const_reference_cstring('hello, world')
'hello, world'
>>> rewrap_const_reference_string('yo, wassup?')
'yo, wassup?'
Now check implicit conversions between floating/integer types
>>> rewrap_const_reference_float(42)
42.0
>>> rewrap_const_reference_int(42.0)
42
>>> rewrap_value_float(42)
42.0
>>> rewrap_value_int(42.0)
42
"""
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])