mirror of
https://github.com/boostorg/python.git
synced 2026-01-24 18:12:43 +00:00
Major rearchitecture of from_python mechanism
[SVN r12924]
This commit is contained in:
34
Jamfile
34
Jamfile
@@ -4,14 +4,18 @@ subproject libs/python ;
|
||||
SEARCH on <module@>python.jam = $(BOOST_BUILD_PATH) ;
|
||||
include <module@>python.jam ;
|
||||
|
||||
PYTHON_PROPERTIES
|
||||
+= <metrowerks><*><cxxflags>"-inline deferred"
|
||||
<cxx><*><include>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers
|
||||
<define>BOOST_PYTHON_DYNAMIC_LIB
|
||||
<define>BOOST_PYTHON_V2
|
||||
;
|
||||
|
||||
{
|
||||
local BOOST_PYTHON_V2_PROPERTIES
|
||||
= $(PYTHON_PROPERTIES)
|
||||
<metrowerks><*><cxxflags>"-inline deferred"
|
||||
<cxx><*><include>$(BOOST_ROOT)/boost/compatibility/cpp_c_headers
|
||||
<define>BOOST_PYTHON_DYNAMIC_LIB
|
||||
<define>BOOST_PYTHON_V2
|
||||
;
|
||||
|
||||
local PYTHON_PROPERTIES = $(BOOST_PYTHON_V2_PROPERTIES) ;
|
||||
|
||||
dll bpl
|
||||
:
|
||||
src/converter/from_python.cpp
|
||||
@@ -26,7 +30,7 @@ PYTHON_PROPERTIES
|
||||
src/objects.cpp
|
||||
src/converter/builtin_converters.cpp
|
||||
:
|
||||
$(PYTHON_PROPERTIES)
|
||||
$(BOOST_PYTHON_V2_PROPERTIES)
|
||||
<define>BOOST_PYTHON_SOURCE
|
||||
;
|
||||
|
||||
@@ -67,4 +71,20 @@ PYTHON_PROPERTIES
|
||||
:
|
||||
: debug-python
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
unit-test indirect_traits_test
|
||||
: test/indirect_traits_test.cpp : <include>$(BOOST_ROOT) ;
|
||||
unit-test destroy_test
|
||||
: test/destroy_test.cpp : <include>$(BOOST_ROOT) ;
|
||||
unit-test pointer_type_id_test
|
||||
: test/pointer_type_id_test.cpp : <include>$(BOOST_ROOT) ;
|
||||
|
||||
unit-test select_from_python_test
|
||||
: test/select_from_python_test.cpp
|
||||
src/converter/type_id.cpp
|
||||
src/converter/registry.cpp # MWerks needs this for some reason
|
||||
: $(PYTHON_PROPERTIES)
|
||||
;
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ module& setattr(const char* name, ref const& r);
|
||||
<dt><b>Effects:</b> Adds the given Python object to the module. If the
|
||||
object is a product of <code><a href=
|
||||
"make_function.html#make_function-spec">make_function</a>()</code>, the
|
||||
usual <a href="http:overloading.html">overloading procedure</a> applies.
|
||||
usual <a href="overloading.html">overloading procedure</a> applies.
|
||||
In the first two forms, ownership of a reference to obj is transferred
|
||||
from caller to callee, even if an exception is thrown.
|
||||
|
||||
|
||||
@@ -1,62 +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 BODY_DWA2001127_HPP
|
||||
# define BODY_DWA2001127_HPP
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/converter/type_id.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
namespace registry
|
||||
{
|
||||
class entry;
|
||||
}
|
||||
|
||||
struct BOOST_PYTHON_DECL body
|
||||
{
|
||||
public:
|
||||
body(type_id_t key);
|
||||
virtual ~body() {}
|
||||
|
||||
type_id_t key() const;
|
||||
|
||||
protected:
|
||||
// true iff the registry is still alive
|
||||
bool can_unregister() const;
|
||||
|
||||
private:
|
||||
// called when the registry is destroyed, to prevent it from being
|
||||
// unregistered.
|
||||
void do_not_unregister();
|
||||
friend class registry::entry;
|
||||
|
||||
private:
|
||||
type_id_t m_key;
|
||||
bool m_can_unregister;
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
inline body::body(type_id_t key)
|
||||
: m_key(key)
|
||||
, m_can_unregister(true)
|
||||
{
|
||||
}
|
||||
|
||||
inline type_id_t body::key() const
|
||||
{
|
||||
return m_key;
|
||||
}
|
||||
|
||||
inline bool body::can_unregister() const
|
||||
{
|
||||
return m_can_unregister;
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // BODY_DWA2001127_HPP
|
||||
@@ -1,75 +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_DWA20011215_HPP
|
||||
# define CLASS_DWA20011215_HPP
|
||||
|
||||
# include <boost/python/object/class.hpp>
|
||||
# include <boost/python/converter/from_python.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class T>
|
||||
struct class_from_python_converter
|
||||
{
|
||||
class_from_python_converter();
|
||||
|
||||
static void* convertible(PyObject*);
|
||||
static T& convert_ref(PyObject*, from_python_data&);
|
||||
static T const& convert_cref(PyObject*, from_python_data&);
|
||||
static T* convert_ptr(PyObject*, from_python_data&);
|
||||
static T const* convert_cptr(PyObject*, from_python_data&);
|
||||
|
||||
from_python_converter<T&> to_ref;
|
||||
from_python_converter<T const&> to_cref;
|
||||
from_python_converter<T*> to_ptr;
|
||||
from_python_converter<T const*> to_cptr;
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
template <class T>
|
||||
class_from_python_converter<T>::class_from_python_converter()
|
||||
: to_ref(convertible, convert_ref)
|
||||
, to_cref(convertible, convert_cref)
|
||||
, to_ptr(convertible, convert_ptr)
|
||||
, to_cptr(convertible, convert_cptr)
|
||||
{}
|
||||
|
||||
template <class T>
|
||||
T& class_from_python_converter<T>::convert_ref(PyObject*, from_python_data& x)
|
||||
{
|
||||
return *static_cast<T*>(x.stage1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T const& class_from_python_converter<T>::convert_cref(PyObject*, from_python_data& x)
|
||||
{
|
||||
return *static_cast<T*>(x.stage1);
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
T* class_from_python_converter<T>::convert_ptr(PyObject*, from_python_data& x)
|
||||
{
|
||||
return static_cast<T*>(x.stage1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T const* class_from_python_converter<T>::convert_cptr(PyObject*, from_python_data& x)
|
||||
{
|
||||
return static_cast<T*>(x.stage1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void* class_from_python_converter<T>::convertible(PyObject* p)
|
||||
{
|
||||
return objects::find_instance<T>(p);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // CLASS_DWA20011215_HPP
|
||||
25
include/boost/python/converter/find_from_python.hpp
Normal file
25
include/boost/python/converter/find_from_python.hpp
Normal 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 FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
# define FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct lvalue_from_python_registration;
|
||||
struct rvalue_from_python_registration;
|
||||
struct rvalue_stage1_data;
|
||||
|
||||
BOOST_PYTHON_DECL void* find(
|
||||
PyObject* source, lvalue_from_python_registration const*);
|
||||
BOOST_PYTHON_DECL void* find(
|
||||
PyObject* source, rvalue_from_python_registration const*, rvalue_stage1_data&);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
@@ -6,193 +6,279 @@
|
||||
#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/registry.hpp>
|
||||
# include <boost/python/converter/find_from_python.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/utility.hpp>
|
||||
# include <boost/python/detail/destroy.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/python/converter/pointer_type_id.hpp>
|
||||
# include <boost/python/converter/from_python_data.hpp>
|
||||
# include <boost/mpl/select_type.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
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
|
||||
struct from_python_base
|
||||
{
|
||||
from_python_converter_base(type_id_t, from_python_check); // registers
|
||||
public: // member functions
|
||||
from_python_base(void* result);
|
||||
from_python_base(PyObject*, lvalue_from_python_registration const* chain);
|
||||
bool convertible() const;
|
||||
|
||||
protected: // member functions
|
||||
void*const& result() const;
|
||||
|
||||
private: // data members
|
||||
void* m_result;
|
||||
};
|
||||
|
||||
// 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;
|
||||
|
||||
// Given the head of a from_python converter chain, find the
|
||||
// converter which can convert p, leaving its intermediate data in
|
||||
// data.
|
||||
inline static from_python_converter_base const*
|
||||
find(from_python_converter_base const*chain, PyObject* p, void*& data);
|
||||
// Used when T == U*const&
|
||||
template <class T>
|
||||
struct pointer_const_reference_from_python
|
||||
{
|
||||
pointer_const_reference_from_python(PyObject*);
|
||||
T operator()(PyObject*) const;
|
||||
bool convertible() const;
|
||||
|
||||
private:
|
||||
from_python_check m_convertible;
|
||||
from_python_converter_base* m_next;
|
||||
detail::referent_storage<T>::type m_result;
|
||||
|
||||
static lvalue_from_python_registration*& chain;
|
||||
};
|
||||
|
||||
|
||||
// Used when T == U*
|
||||
template <class T>
|
||||
struct from_python_converter : from_python_converter_base
|
||||
struct pointer_from_python : from_python_base
|
||||
{
|
||||
public: // types
|
||||
typedef typename from_python_function<T>::type conversion_function;
|
||||
pointer_from_python(PyObject*);
|
||||
T operator()(PyObject*) const;
|
||||
|
||||
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;
|
||||
|
||||
// Find a converter for converting p to a T.
|
||||
static from_python_converter<T> const* find(PyObject* p, void*& data);
|
||||
|
||||
private: // data members
|
||||
conversion_function m_convert;
|
||||
from_python_destructor m_destroy;
|
||||
|
||||
// Keeps the chain of converters which convert from PyObject* to T
|
||||
static from_python_converter_base*const& chain;
|
||||
static lvalue_from_python_registration*& chain;
|
||||
};
|
||||
|
||||
// Initialized to refer to a common place in the registry.
|
||||
// Used when T == U& and (T != V const& or T == W volatile&)
|
||||
template <class T>
|
||||
from_python_converter_base*const&
|
||||
from_python_converter<T>::chain = registry::from_python_chain(type_id<T>());
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
// A class which implements from_python with a registry lookup.
|
||||
template <class T>
|
||||
struct from_python_lookup // : from_python_base
|
||||
struct reference_from_python : from_python_base
|
||||
{
|
||||
public: // types
|
||||
reference_from_python(PyObject*);
|
||||
T operator()(PyObject*) const;
|
||||
|
||||
public: // member functions
|
||||
from_python_lookup(PyObject* source);
|
||||
~from_python_lookup();
|
||||
static lvalue_from_python_registration*& chain;
|
||||
};
|
||||
|
||||
// ------- rvalue converters ---------
|
||||
|
||||
// Used for the case where T is a non-pointer, non-reference type OR
|
||||
// is a const non-volatile reference to a non-pointer type.
|
||||
template <class T>
|
||||
class rvalue_from_python
|
||||
{
|
||||
typedef typename boost::add_reference<
|
||||
typename boost::add_const<T>::type
|
||||
>::type result_type;
|
||||
|
||||
public:
|
||||
rvalue_from_python(PyObject*);
|
||||
~rvalue_from_python();
|
||||
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;
|
||||
result_type operator()(PyObject*);
|
||||
|
||||
private:
|
||||
rvalue_data<result_type> m_data;
|
||||
static rvalue_from_python_registration*& chain;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct select_from_python
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ptr = is_pointer<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ptr_cref
|
||||
= boost::python::detail::is_reference_to_pointer<T>::value
|
||||
&& boost::python::detail::is_reference_to_const<T>::value
|
||||
&& !boost::python::detail::is_reference_to_volatile<T>::value);
|
||||
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ref =
|
||||
boost::python::detail::is_reference_to_non_const<T>::value
|
||||
|| boost::python::detail::is_reference_to_volatile<T>::value);
|
||||
|
||||
typedef typename mpl::select_type<
|
||||
ptr
|
||||
, pointer_from_python<T>
|
||||
, typename mpl::select_type<
|
||||
ptr_cref
|
||||
, pointer_const_reference_from_python<T>
|
||||
, typename mpl::select_type<
|
||||
ref
|
||||
, reference_from_python<T>
|
||||
, rvalue_from_python<T>
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
inline void* from_python_converter_base::convertible(PyObject* o) const
|
||||
inline from_python_base::from_python_base(void* result)
|
||||
: m_result(result)
|
||||
{
|
||||
return m_convertible(o);
|
||||
}
|
||||
|
||||
inline from_python_converter_base const*
|
||||
from_python_converter_base::find(
|
||||
from_python_converter_base const* chain, PyObject* p, void*& data)
|
||||
inline from_python_base::from_python_base(
|
||||
PyObject* const source
|
||||
, lvalue_from_python_registration const* chain)
|
||||
: m_result(find(source, chain))
|
||||
{
|
||||
for (from_python_converter_base const* q = chain; q != 0 ; q = q->m_next)
|
||||
{
|
||||
void* d = q->convertible(p);
|
||||
if (d != 0)
|
||||
{
|
||||
data = d;
|
||||
return q;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool from_python_base::convertible() const
|
||||
{
|
||||
return m_result != 0;
|
||||
}
|
||||
|
||||
inline void*const& from_python_base::result() const
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
// --------
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class U>
|
||||
inline U& void_ptr_to_reference(void const volatile* p, U&(*)())
|
||||
{
|
||||
return *(U*)p;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct null_ptr_owner
|
||||
{
|
||||
static T value;
|
||||
};
|
||||
template <class T> T null_ptr_owner<T>::value = 0;
|
||||
|
||||
template <class U>
|
||||
inline U& null_ptr_reference(U&(*)())
|
||||
{
|
||||
return null_ptr_owner<U>::value;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void write_void_ptr(void const volatile* storage, void* ptr, T*)
|
||||
{
|
||||
*(T**)storage = (T*)ptr;
|
||||
}
|
||||
|
||||
// writes U(ptr) into the storage
|
||||
template <class U>
|
||||
inline void write_void_ptr_reference(void const volatile* storage, void* ptr, U&(*)())
|
||||
{
|
||||
write_void_ptr(storage, ptr, U(0));
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
inline pointer_const_reference_from_python<T>::pointer_const_reference_from_python(PyObject* p)
|
||||
{
|
||||
detail::write_void_ptr_reference(
|
||||
m_result.bytes
|
||||
, p == Py_None ? p : find(p, chain)
|
||||
, (T(*)())0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool pointer_const_reference_from_python<T>::convertible() const
|
||||
{
|
||||
return detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0;
|
||||
}
|
||||
template <class T>
|
||||
inline T pointer_const_reference_from_python<T>::operator()(PyObject* p) const
|
||||
{
|
||||
return (p == Py_None)
|
||||
? detail::null_ptr_reference((T(*)())0)
|
||||
: detail::void_ptr_to_reference(m_result.bytes, (T(*)())0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
lvalue_from_python_registration*& pointer_const_reference_from_python<T>::chain
|
||||
= registry::lvalue_converters(pointer_type_id<T>());
|
||||
|
||||
// --------
|
||||
|
||||
template <class T>
|
||||
inline pointer_from_python<T>::pointer_from_python(PyObject* p)
|
||||
: from_python_base(p == Py_None ? p : find(p, chain))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T pointer_from_python<T>::operator()(PyObject* p) const
|
||||
{
|
||||
return (p == Py_None) ? 0 : T(result());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
lvalue_from_python_registration*& pointer_from_python<T>::chain
|
||||
= registry::lvalue_converters(pointer_type_id<T>());
|
||||
|
||||
// --------
|
||||
|
||||
template <class T>
|
||||
inline reference_from_python<T>::reference_from_python(PyObject* p)
|
||||
: from_python_base(find(p,chain))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T reference_from_python<T>::operator()(PyObject*) const
|
||||
{
|
||||
return detail::void_ptr_to_reference(result(), (T(*)())0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
lvalue_from_python_registration*& reference_from_python<T>::chain
|
||||
= registry::lvalue_converters(undecorated_type_id<T>());
|
||||
|
||||
// -------
|
||||
|
||||
template <class T>
|
||||
inline rvalue_from_python<T>::rvalue_from_python(PyObject* obj)
|
||||
{
|
||||
find(obj, chain, m_data.stage1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline rvalue_from_python<T>::~rvalue_from_python()
|
||||
{
|
||||
if (m_data.stage1.convertible == m_data.storage.bytes)
|
||||
python::detail::destroy_reference<result_type>(m_data.storage.bytes);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool rvalue_from_python<T>::convertible() const
|
||||
{
|
||||
return m_data.stage1.convertible != 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename rvalue_from_python<T>::result_type
|
||||
rvalue_from_python<T>::operator()(PyObject* p)
|
||||
{
|
||||
if (m_data.stage1.construct != 0)
|
||||
m_data.stage1.construct(p, &m_data.stage1);
|
||||
|
||||
return detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline from_python_converter<T> const*
|
||||
from_python_converter<T>::find(PyObject* p, void*& data)
|
||||
{
|
||||
return static_cast<from_python_converter<T> const*>(
|
||||
from_python_converter_base::find(chain, p, data));
|
||||
}
|
||||
|
||||
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(
|
||||
from_python_converter<T>::find(
|
||||
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;
|
||||
}
|
||||
rvalue_from_python_registration*& rvalue_from_python<T>::chain
|
||||
= registry::rvalue_converters(undecorated_type_id<T>());
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
|
||||
@@ -9,26 +9,20 @@
|
||||
# include <boost/python/detail/char_array.hpp>
|
||||
# include <boost/mpl/select_type.hpp>
|
||||
# include <boost/type_traits/same_traits.hpp>
|
||||
# include <boost/type.hpp>
|
||||
# include <boost/type_traits/alignment_traits.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/static_assert.hpp>
|
||||
# include <boost/python/converter/from_python_stage1_data.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;
|
||||
@@ -74,8 +68,8 @@ namespace detail
|
||||
|
||||
template <class T> struct referent_size
|
||||
{
|
||||
static T t;
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(t));
|
||||
static T f();
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(f()));
|
||||
};
|
||||
|
||||
# endif
|
||||
@@ -130,17 +124,13 @@ namespace detail
|
||||
#endif // EDG is too slow
|
||||
|
||||
template <class Align, std::size_t size>
|
||||
struct aligned_storage
|
||||
union 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)];
|
||||
};
|
||||
Align align;
|
||||
char bytes[size
|
||||
// this is just a STATIC_ASSERT. For some reason
|
||||
// MSVC was barfing on the boost one.
|
||||
- (is_same<Align,unknown_alignment>::value ? size : 0)];
|
||||
};
|
||||
|
||||
template <class Reference>
|
||||
@@ -151,56 +141,39 @@ namespace detail
|
||||
typedef mpl::for_each<
|
||||
align_types
|
||||
, unknown_alignment
|
||||
, best_alignment_type<referent_alignment<Reference>::value>
|
||||
, 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
|
||||
|
||||
|
||||
#endif
|
||||
BOOST_STATIC_CONSTANT(std::size_t, alignment1 = alignment_of<align_t>::value);
|
||||
BOOST_STATIC_CONSTANT(std::size_t, alignment2 = referent_alignment<Reference>::value);
|
||||
|
||||
BOOST_STATIC_ASSERT(alignment1 >= alignment2);
|
||||
BOOST_STATIC_ASSERT(alignment1 % alignment2 == 0);
|
||||
|
||||
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
|
||||
struct rvalue_data
|
||||
{
|
||||
typedef typename mpl::select_type<
|
||||
is_reference<T>::value, T, void>::type just_reference_t;
|
||||
|
||||
typedef detail::intermediate_data<just_reference_t> type;
|
||||
rvalue_stage1_data stage1;
|
||||
|
||||
typename detail::referent_storage<
|
||||
typename add_reference<T>::type
|
||||
>::type storage;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
@@ -10,13 +10,8 @@
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct from_python_data;
|
||||
|
||||
template <class T>
|
||||
struct from_python_function
|
||||
{
|
||||
typedef T (*type)(PyObject*, from_python_data&);
|
||||
};
|
||||
struct rvalue_stage1_data;
|
||||
typedef void (*constructor_function)(PyObject* source, rvalue_stage1_data*);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
|
||||
21
include/boost/python/converter/from_python_stage1_data.hpp
Normal file
21
include/boost/python/converter/from_python_stage1_data.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// 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_STAGE1_DATA_DWA2002223_HPP
|
||||
# define FROM_PYTHON_STAGE1_DATA_DWA2002223_HPP
|
||||
|
||||
# include <boost/python/converter/from_python_function.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct rvalue_stage1_data
|
||||
{
|
||||
void* convertible;
|
||||
constructor_function construct;
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // FROM_PYTHON_STAGE1_DATA_DWA2002223_HPP
|
||||
28
include/boost/python/converter/registrations.hpp
Normal file
28
include/boost/python/converter/registrations.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
// 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 REGISTRATIONS_DWA2002223_HPP
|
||||
# define REGISTRATIONS_DWA2002223_HPP
|
||||
|
||||
# include <boost/python/converter/from_python_function.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct lvalue_from_python_registration
|
||||
{
|
||||
void* (*convert)(PyObject* source);
|
||||
lvalue_from_python_registration* next;
|
||||
};
|
||||
|
||||
struct rvalue_from_python_registration
|
||||
{
|
||||
void* (*convertible)(PyObject*);
|
||||
constructor_function construct;
|
||||
rvalue_from_python_registration* next;
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // REGISTRATIONS_DWA2002223_HPP
|
||||
@@ -9,20 +9,33 @@
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/converter/to_python_function.hpp>
|
||||
# include <boost/python/converter/from_python_function.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct BOOST_PYTHON_DECL from_python_converter_base;
|
||||
struct lvalue_from_python_registration;
|
||||
struct rvalue_from_python_registration;
|
||||
|
||||
// This namespace acts as a sort of singleton
|
||||
namespace registry
|
||||
{
|
||||
BOOST_PYTHON_DECL lvalue_from_python_registration*& lvalue_converters(undecorated_type_id_t);
|
||||
BOOST_PYTHON_DECL rvalue_from_python_registration*& rvalue_converters(undecorated_type_id_t);
|
||||
|
||||
BOOST_PYTHON_DECL to_python_value_function const&
|
||||
to_python_function(undecorated_type_id_t);
|
||||
|
||||
BOOST_PYTHON_DECL void insert(to_python_value_function, undecorated_type_id_t);
|
||||
|
||||
BOOST_PYTHON_DECL from_python_converter_base*& from_python_chain(type_id_t);
|
||||
|
||||
// Insert an lvalue from_python converter
|
||||
BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), undecorated_type_id_t);
|
||||
|
||||
// Insert an rvalue from_python converter
|
||||
BOOST_PYTHON_DECL void insert(
|
||||
void* (*convertible)(PyObject*)
|
||||
, constructor_function
|
||||
, undecorated_type_id_t
|
||||
);
|
||||
|
||||
BOOST_PYTHON_DECL PyTypeObject*& class_object(undecorated_type_id_t key);
|
||||
}
|
||||
|
||||
@@ -1,191 +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 TARGET_DWA20011119_HPP
|
||||
# define TARGET_DWA20011119_HPP
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/object_traits.hpp>
|
||||
# include <boost/mpl/select_type.hpp>
|
||||
# include <boost/type_traits/same_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// target --
|
||||
//
|
||||
// This type generator (see
|
||||
// ../../../more/generic_programming.html#type_generator) is used
|
||||
// to select the return type of the appropriate converter for
|
||||
// unwrapping a given type.
|
||||
|
||||
// Strategy:
|
||||
//
|
||||
// 1. reduce everything to a common, un-cv-qualified reference
|
||||
// type where possible. This will save on registering many different
|
||||
// converter types.
|
||||
//
|
||||
// 2. Treat built-in types specially: when unwrapping a value or
|
||||
// constant reference to one of these, use a value for the target
|
||||
// type. It will bind to a const reference if neccessary, and more
|
||||
// importantly, avoids having to dynamically allocate room for
|
||||
// an lvalue of types which can be cheaply copied.
|
||||
//
|
||||
|
||||
// Target Source
|
||||
// int int
|
||||
// int const& int
|
||||
// int& int&
|
||||
// int volatile& int volatile&
|
||||
// int const volatile& int const volatile&
|
||||
|
||||
// On compilers supporting partial specialization:
|
||||
//
|
||||
// Target Source
|
||||
// T T const&
|
||||
// T& T&
|
||||
// T const& T const&
|
||||
// T volatile T&
|
||||
// T const volatile& T const&
|
||||
// T* T*
|
||||
// T const* T const*
|
||||
// T volatile T*
|
||||
// T const volatile* T const*
|
||||
// T cv*const& same as T cv*
|
||||
// T cv*& T*& <- should this be legal?
|
||||
// T cv*volatile& T*& <- should this be legal?
|
||||
// T cv*const volatile& T*& <- should this be legal?
|
||||
|
||||
// On others:
|
||||
//
|
||||
// Target Source
|
||||
// T T&
|
||||
// T cv& T cv&
|
||||
// T cv* T cv*
|
||||
// T cv*cv& T cv*cv&
|
||||
|
||||
// As you can see, in order to handle the same range of types without
|
||||
// partial specialization, more converters need to be registered.
|
||||
|
||||
template <class T>
|
||||
struct target
|
||||
{
|
||||
// Some pointer types are handled in a more sophisticated way on
|
||||
// compilers supporting partial specialization.
|
||||
BOOST_STATIC_CONSTANT(bool, use_identity = (::boost::is_scalar<T>::value));
|
||||
|
||||
typedef typename mpl::select_type<
|
||||
use_identity
|
||||
, T
|
||||
, typename add_reference<
|
||||
typename add_const<
|
||||
typename remove_volatile<T>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
// When partial specialization is not present, we'll simply need to
|
||||
// register many more converters.
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
template <class T>
|
||||
struct target<T&>
|
||||
{
|
||||
typedef typename remove_volatile<T>::type& type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct target<T const&>
|
||||
{
|
||||
typedef typename boost::mpl::select_type<
|
||||
is_scalar<T>::value
|
||||
, typename remove_cv<T>::type
|
||||
, typename remove_volatile<T>::type const&
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct target<T*>
|
||||
{
|
||||
typedef typename remove_volatile<T>::type* type;
|
||||
};
|
||||
|
||||
// Handle T*-cv for completeness. Function arguments in a signature
|
||||
// are never actually cv-qualified, but who knows how these converters
|
||||
// might be used, or whether compiler bugs lurk which make it seem
|
||||
// otherwise?
|
||||
template <class T>
|
||||
struct target<T* const>
|
||||
{
|
||||
typedef typename remove_volatile<T>::type* type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct target<T* volatile>
|
||||
{
|
||||
typedef typename remove_volatile<T>::type* type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct target<T* const volatile>
|
||||
{
|
||||
typedef typename remove_volatile<T>::type* type;
|
||||
};
|
||||
|
||||
// non-const references to pointers should be handled by the
|
||||
// specialization for T&, above.
|
||||
template <class T>
|
||||
struct target<T* const&>
|
||||
{
|
||||
typedef typename remove_volatile<T>::type* type;
|
||||
};
|
||||
# endif
|
||||
|
||||
// Fortunately, we can handle T const& where T is an arithmetic type
|
||||
// by explicit specialization. These specializations will cause value
|
||||
// and const& arguments to be converted to values, rather than to
|
||||
// references.
|
||||
# define BOOST_PYTHON_UNWRAP_VALUE(T) \
|
||||
template <> \
|
||||
struct target<T> \
|
||||
{ \
|
||||
typedef T type; \
|
||||
}; \
|
||||
template <> \
|
||||
struct target<T const> \
|
||||
{ \
|
||||
typedef T type; \
|
||||
}; \
|
||||
template <> \
|
||||
struct target<T volatile> \
|
||||
{ \
|
||||
typedef T type; \
|
||||
}; \
|
||||
template <> \
|
||||
struct target<T const volatile> \
|
||||
{ \
|
||||
typedef T type; \
|
||||
}; \
|
||||
template <> \
|
||||
struct target<T const&> \
|
||||
{ \
|
||||
typedef T type; \
|
||||
}
|
||||
|
||||
BOOST_PYTHON_UNWRAP_VALUE(char);
|
||||
BOOST_PYTHON_UNWRAP_VALUE(unsigned char);
|
||||
BOOST_PYTHON_UNWRAP_VALUE(signed char);
|
||||
BOOST_PYTHON_UNWRAP_VALUE(unsigned int);
|
||||
BOOST_PYTHON_UNWRAP_VALUE(signed int);
|
||||
BOOST_PYTHON_UNWRAP_VALUE(unsigned short);
|
||||
BOOST_PYTHON_UNWRAP_VALUE(signed short);
|
||||
BOOST_PYTHON_UNWRAP_VALUE(unsigned long);
|
||||
BOOST_PYTHON_UNWRAP_VALUE(signed long);
|
||||
BOOST_PYTHON_UNWRAP_VALUE(char const*);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // TARGET_DWA20011119_HPP
|
||||
@@ -1,36 +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 UNWRAPPER_BASE_DWA20011215_HPP
|
||||
# define UNWRAPPER_BASE_DWA20011215_HPP
|
||||
# include <boost/python/converter/type_id.hpp>
|
||||
# include <boost/python/converter/body.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/config.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct BOOST_PYTHON_DECL unwrapper_base : body
|
||||
{
|
||||
public:
|
||||
unwrapper_base(type_id_t); // registers
|
||||
~unwrapper_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.
|
||||
virtual void* can_convert(PyObject*) const = 0;
|
||||
|
||||
protected:
|
||||
// this is an arbitrary non-null pointer you can use to indicate success
|
||||
static void* const non_null;
|
||||
|
||||
private: // body required interface implementation
|
||||
void destroy_handle(handle*) const {}
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // UNWRAPPER_BASE_DWA20011215_HPP
|
||||
83
include/boost/python/detail/destroy.hpp
Normal file
83
include/boost/python/detail/destroy.hpp
Normal file
@@ -0,0 +1,83 @@
|
||||
// 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 DESTROY_DWA2002221_HPP
|
||||
# define DESTROY_DWA2002221_HPP
|
||||
|
||||
# include <boost/type_traits/composite_traits.hpp>
|
||||
# include <boost/type_traits/object_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
template <bool array, bool trivial_destructor> struct value_destroyer;
|
||||
|
||||
template <>
|
||||
struct value_destroyer<false,false>
|
||||
{
|
||||
template <class T>
|
||||
static void execute(T const volatile* p)
|
||||
{
|
||||
p->T::~T();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct value_destroyer<true,false>
|
||||
{
|
||||
template <class A, class T>
|
||||
static void execute(A*, T const volatile* const first)
|
||||
{
|
||||
for (T const volatile* p = first; p != first + sizeof(A)/sizeof(T); ++p)
|
||||
value_destroyer<
|
||||
boost::is_array<T>::value
|
||||
,boost::has_trivial_destructor<T>::value
|
||||
>::execute(p);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void execute(T const volatile* p)
|
||||
{
|
||||
execute(p, *p);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct value_destroyer<true,true>
|
||||
{
|
||||
template <class T>
|
||||
static void execute(T const volatile* p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct value_destroyer<false,true>
|
||||
{
|
||||
template <class T>
|
||||
static void execute(T const volatile* p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline void destroy_reference_impl(void* p, T& (*)())
|
||||
{
|
||||
// note: cv-qualification needed for MSVC6
|
||||
// must come *before* T for metrowerks
|
||||
value_destroyer<
|
||||
(boost::is_array<T>::value)
|
||||
, (boost::has_trivial_destructor<T>::value)
|
||||
>::execute((const volatile T*)p);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void destroy_reference(void* p, T(*)() = 0)
|
||||
{
|
||||
destroy_reference_impl(p, (T(*)())0);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // DESTROY_DWA2002221_HPP
|
||||
@@ -7,15 +7,14 @@
|
||||
# define FROM_PYTHON_DWA2002128_HPP
|
||||
|
||||
# include <boost/python/converter/from_python.hpp>
|
||||
# include <boost/python/converter/target.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T>
|
||||
struct from_python
|
||||
: converter::from_python_lookup<typename converter::target<T>::type>
|
||||
: converter::select_from_python<T>::type
|
||||
{
|
||||
typedef converter::from_python_lookup<typename converter::target<T>::type> base;
|
||||
typedef typename converter::select_from_python<T>::type base;
|
||||
from_python(PyObject*);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
// 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 LVALUE_FROM_PYTHON_DWA2002130_HPP
|
||||
# define LVALUE_FROM_PYTHON_DWA2002130_HPP
|
||||
|
||||
# include <boost/python/converter/from_python.hpp>
|
||||
# include <boost/python/type_from_python.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
// Utility which produces a member extractor function on platforms
|
||||
// other than VC6.
|
||||
template <class Class, class Member, Member (Class::*mp)>
|
||||
struct get_member
|
||||
{
|
||||
static Member& execute(Class& c)
|
||||
{
|
||||
return c.*mp;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class Class>
|
||||
struct extract_identity
|
||||
{
|
||||
static Class& execute(Class& c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <
|
||||
PyTypeObject const* python_type
|
||||
, class Value
|
||||
, class PythonObject = Value
|
||||
, class Extract = detail::extract_identity<Value>
|
||||
>
|
||||
class lvalue_from_python
|
||||
{
|
||||
typedef type_from_python<python_type> convertible_t;
|
||||
public:
|
||||
|
||||
lvalue_from_python()
|
||||
: m_mutable_converter(
|
||||
&convertible_t::convertible, convert_mutable)
|
||||
|
||||
, m_const_converter(
|
||||
&convertible_t::convertible, convert_const)
|
||||
|
||||
, m_mutable_pointer_converter(
|
||||
&convertible_t::convertible, convert_mutable_pointer)
|
||||
|
||||
, m_const_pointer_converter(
|
||||
&convertible_t::convertible, convert_const_pointer)
|
||||
{}
|
||||
|
||||
private:
|
||||
static Value& convert_mutable(PyObject* op, converter::from_python_data&)
|
||||
{
|
||||
return Extract::execute(*(PythonObject*)op);
|
||||
}
|
||||
|
||||
static Value const& convert_const(PyObject* op, converter::from_python_data&)
|
||||
{
|
||||
return Extract::execute(*(PythonObject*)op);
|
||||
}
|
||||
|
||||
static Value* convert_mutable_pointer(PyObject* op, converter::from_python_data&)
|
||||
{
|
||||
return &Extract::execute(*(PythonObject*)op);
|
||||
}
|
||||
|
||||
static Value const* convert_const_pointer(PyObject* op, converter::from_python_data&)
|
||||
{
|
||||
return &Extract::execute(*(PythonObject*)op);
|
||||
}
|
||||
|
||||
typedef converter::from_python_converter<Value&> mutable_converter;
|
||||
typedef converter::from_python_converter<Value const&> const_converter;
|
||||
typedef converter::from_python_converter<Value*> mutable_pointer_converter;
|
||||
typedef converter::from_python_converter<Value const*> const_pointer_converter;
|
||||
|
||||
mutable_converter m_mutable_converter;
|
||||
const_converter m_const_converter;
|
||||
mutable_pointer_converter m_mutable_pointer_converter;
|
||||
const_pointer_converter m_const_pointer_converter;
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // LVALUE_FROM_PYTHON_DWA2002130_HPP
|
||||
@@ -53,7 +53,7 @@ struct BOOST_PYTHON_DECL instance_holder : private noncopyable
|
||||
// return the next holder in a chain
|
||||
instance_holder* next() const;
|
||||
|
||||
virtual void* holds(converter::type_id_t) = 0;
|
||||
virtual void* holds(converter::undecorated_type_id_t) = 0;
|
||||
|
||||
void install(PyObject* inst) throw();
|
||||
|
||||
@@ -85,15 +85,19 @@ struct instance
|
||||
instance_holder* objects;
|
||||
};
|
||||
|
||||
// Given a type_id, find the instance data which corresponds to it, or
|
||||
// return 0 in case no such type is held.
|
||||
BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, converter::type_id_t);
|
||||
// Given an undecorated type_id, find the instance data which
|
||||
// corresponds to it, or return 0 in case no such type is held.
|
||||
BOOST_PYTHON_DECL void* find_instance_impl(PyObject*, converter::undecorated_type_id_t);
|
||||
|
||||
// This produces a function with the right signature for use in from_python conversions
|
||||
template <class T>
|
||||
T* find_instance(PyObject* p, T* = 0)
|
||||
struct instance_finder
|
||||
{
|
||||
return static_cast<T*>(find_instance_impl(p, converter::type_id<T>()));
|
||||
}
|
||||
static inline void* execute(PyObject* p)
|
||||
{
|
||||
return find_instance_impl(p, converter::undecorated_type_id<T>());
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_PYTHON_DECL ref class_metatype();
|
||||
BOOST_PYTHON_DECL ref class_type();
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
#ifndef CLASS_CONVERTERS_DWA2002119_HPP
|
||||
# define CLASS_CONVERTERS_DWA2002119_HPP
|
||||
|
||||
# include <boost/python/converter/class.hpp>
|
||||
# include <boost/python/object/class_wrapper.hpp>
|
||||
# include <boost/mpl/for_each.hpp>
|
||||
# include <boost/python/reference.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
@@ -24,7 +24,6 @@ struct class_converters
|
||||
class_converters(ref const& python_class);
|
||||
|
||||
private: // data members
|
||||
converter::class_from_python_converter<Derived> m_unwrapper;
|
||||
class_wrapper<Derived> m_wrapper;
|
||||
};
|
||||
|
||||
@@ -90,6 +89,10 @@ template <class Derived, class Bases>
|
||||
class_converters<Derived,Bases>::class_converters(ref const& type_object)
|
||||
: m_wrapper(type_object)
|
||||
{
|
||||
converter::registry::insert(
|
||||
&instance_finder<Derived>::execute
|
||||
, converter::undecorated_type_id<Derived>());
|
||||
|
||||
// register all up/downcasts here
|
||||
register_dynamic_id<Derived>();
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ struct pointer_holder : instance_holder
|
||||
{}
|
||||
|
||||
private: // required holder implementation
|
||||
void* holds(converter::type_id_t);
|
||||
void* holds(converter::undecorated_type_id_t);
|
||||
|
||||
private: // data members
|
||||
Pointer m_p;
|
||||
@@ -186,12 +186,12 @@ pointer_holder<Pointer,Value>::pointer_holder(Pointer p)
|
||||
}
|
||||
|
||||
template <class Pointer, class Value>
|
||||
void* pointer_holder<Pointer, Value>::holds(converter::type_id_t dst_t)
|
||||
void* pointer_holder<Pointer, Value>::holds(converter::undecorated_type_id_t dst_t)
|
||||
{
|
||||
if (dst_t == converter::type_id<Pointer>())
|
||||
if (dst_t == converter::undecorated_type_id<Pointer>())
|
||||
return &this->m_p;
|
||||
|
||||
converter::type_id_t src_t = converter::type_id<Value>();
|
||||
converter::type_id_t src_t = converter::undecorated_type_id<Value>();
|
||||
return src_t == dst_t ? &*this->m_p
|
||||
: find_dynamic_type(&*this->m_p, src_t, dst_t);
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ struct value_holder : instance_holder
|
||||
{}
|
||||
|
||||
private: // required holder implementation
|
||||
void* holds(converter::type_id_t);
|
||||
void* holds(converter::undecorated_type_id_t);
|
||||
|
||||
private: // data members
|
||||
Held m_held;
|
||||
@@ -151,9 +151,9 @@ struct value_holder_generator
|
||||
};
|
||||
|
||||
template <class Held>
|
||||
void* value_holder<Held>::holds(converter::type_id_t dst_t)
|
||||
void* value_holder<Held>::holds(converter::undecorated_type_id_t dst_t)
|
||||
{
|
||||
converter::type_id_t src_t = converter::type_id<Held>();
|
||||
converter::undecorated_type_id_t src_t = converter::undecorated_type_id<Held>();
|
||||
return src_t == dst_t ? &m_held
|
||||
: find_static_type(&m_held, src_t, dst_t);
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
// 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 REFERENCE_FROM_PYTHON_DWA2002130_HPP
|
||||
# define REFERENCE_FROM_PYTHON_DWA2002130_HPP
|
||||
|
||||
# include <boost/python/converter/from_python.hpp>
|
||||
# include <boost/python/type_from_python.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
// Utility which produces a member extractor function on platforms
|
||||
// other than VC6.
|
||||
template <class Class, class Member, Member (Class::*mp)>
|
||||
struct get_member
|
||||
{
|
||||
static Member& execute(Class* c)
|
||||
{
|
||||
return c->*mp;
|
||||
}
|
||||
};
|
||||
|
||||
template <
|
||||
PyTypeObject const* python_type
|
||||
, class Value
|
||||
, class PythonObject
|
||||
, class Extract
|
||||
>
|
||||
struct reference_from_python
|
||||
{
|
||||
typedef type_from_python<python_type> convertible_t;
|
||||
|
||||
reference_from_python()
|
||||
: 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::execute(*(PythonObject*)op);
|
||||
}
|
||||
|
||||
static Value const& convert_const(PyObject* op, converter::from_python_data&)
|
||||
{
|
||||
return Extract::execute(*(PythonObject*)op);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef converter::from_python_converter<Value&> mutable_converter;
|
||||
typedef converter::from_python_converter<Value const&> const_converter;
|
||||
mutable_converter m_mutable_converter;
|
||||
const_converter m_const_converter;
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // REFERENCE_FROM_PYTHON_DWA2002130_HPP
|
||||
@@ -6,15 +6,94 @@
|
||||
#ifndef TYPE_FROM_PYTHON_DWA2002130_HPP
|
||||
# define TYPE_FROM_PYTHON_DWA2002130_HPP
|
||||
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <PyTypeObject const* python_type>
|
||||
namespace detail
|
||||
{
|
||||
// Given a pointer-to-function of 1 parameter returning a reference
|
||||
// type, return the type_id of the function's return type.
|
||||
template <class T, class U>
|
||||
inline converter::undecorated_type_id_t extractor_type_id(T&(*)(U))
|
||||
{
|
||||
return converter::undecorated_type_id<T>();
|
||||
}
|
||||
|
||||
// A function generator whose static execute() function is an lvalue
|
||||
// from_python converter using the given Extractor. U is exepcted to
|
||||
// be the actual type of the PyObject instance from which the result
|
||||
// is being extracted.
|
||||
template <class Extractor, class U>
|
||||
struct normalized_extractor
|
||||
{
|
||||
static inline void* execute(PyObject* op)
|
||||
{
|
||||
typedef typename boost::add_reference<U>::type param;
|
||||
return &Extractor::execute(
|
||||
boost::python::converter::detail::void_ptr_to_reference(
|
||||
op, (param(*)())0 )
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Given an Extractor type and a pointer to its execute function,
|
||||
// return a new object whose static execute function does the same
|
||||
// job but is a conforming lvalue from_python conversion function.
|
||||
//
|
||||
// usage: normalize<Extractor>(&Extractor::execute)
|
||||
template <class Extractor, class T, class U>
|
||||
inline normalized_extractor<Extractor,U>
|
||||
normalize(T(*)(U), Extractor* = 0)
|
||||
{
|
||||
return normalized_extractor<Extractor, U>();
|
||||
}
|
||||
}
|
||||
|
||||
// An Extractor which extracts the given member from a Python object
|
||||
// whose instances are stored as InstanceType.
|
||||
template <class InstanceType, class MemberType, MemberType (InstanceType::*member)>
|
||||
struct member_extractor
|
||||
{
|
||||
static MemberType& execute(InstanceType& c)
|
||||
{
|
||||
(void)c.ob_type; // static assertion
|
||||
return c.*member;
|
||||
}
|
||||
};
|
||||
|
||||
// An Extractor which simply extracts the entire python object
|
||||
// instance of InstanceType.
|
||||
template <class InstanceType>
|
||||
struct identity_extractor
|
||||
{
|
||||
static InstanceType& execute(InstanceType& c)
|
||||
{
|
||||
(void)c.ob_type; // static assertion
|
||||
return c;
|
||||
}
|
||||
};
|
||||
|
||||
// Registers a from_python conversion which extracts lvalues using
|
||||
// Extractor's static execute function from Python objects whose type
|
||||
// object is python_type.
|
||||
template <PyTypeObject const* python_type, class Extractor>
|
||||
struct type_from_python
|
||||
{
|
||||
static void* convertible(PyObject* op)
|
||||
type_from_python()
|
||||
{
|
||||
return PyObject_TypeCheck(
|
||||
op, const_cast<PyTypeObject*>(python_type)) ? op : 0;
|
||||
converter::registry::insert(
|
||||
&extract, detail::extractor_type_id(&Extractor::execute));
|
||||
}
|
||||
|
||||
static void* extract(PyObject* op)
|
||||
{
|
||||
return PyObject_TypeCheck(op, const_cast<PyTypeObject*>(python_type))
|
||||
? const_cast<void*>(
|
||||
static_cast<void const volatile*>(
|
||||
detail::normalize<Extractor>(&Extractor::execute).execute(op)))
|
||||
: 0
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
// 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 VALUE_FROM_PYTHON_DWA2002130_HPP
|
||||
# define VALUE_FROM_PYTHON_DWA2002130_HPP
|
||||
|
||||
# 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 value_from_python<T,Derived> self;
|
||||
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
|
||||
, &Derived::convert
|
||||
|
||||
// Change this to a compile-time check later to avoid
|
||||
// generating destroy function
|
||||
, has_trivial_destructor<T>::value ? 0 : &Derived::destroy
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
static void* get_storage(converter::from_python_data& data)
|
||||
{
|
||||
return converter::get_storage<T const&>(data);
|
||||
}
|
||||
|
||||
// Mark successful construction
|
||||
static void constructed(converter::from_python_data& data)
|
||||
{
|
||||
data.stage1 = self::get_storage(data);
|
||||
}
|
||||
|
||||
inline static void destroy(converter::from_python_data& data)
|
||||
{
|
||||
// Get the location of the storage for
|
||||
void* storage = self::get_storage(data);
|
||||
|
||||
// Check for successful construction
|
||||
if (data.stage1 == storage)
|
||||
static_cast<T*>(storage)->~T();
|
||||
}
|
||||
|
||||
private:
|
||||
converter::from_python_converter<T const&> m_converter;
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // VALUE_FROM_PYTHON_DWA2002130_HPP
|
||||
@@ -1,18 +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.
|
||||
#include <boost/python/converter/body.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// default implementation is a no-op. Most handles will not hold any
|
||||
// data that needs to be managed. Unwrap objects which convert
|
||||
// by-value are an exception. Fortunately, the concrete body subclass
|
||||
// has that knowledge.
|
||||
void body::destroy_handle(handle*) const
|
||||
{
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
@@ -7,177 +7,120 @@
|
||||
#include <boost/python/detail/config.hpp>
|
||||
#include <boost/python/detail/wrap_python.hpp>
|
||||
#include <boost/python/converter/builtin_converters.hpp>
|
||||
#include <boost/python/converter/target.hpp>
|
||||
#include <boost/python/value_from_python.hpp>
|
||||
#include <boost/python/converter/from_python_data.hpp>
|
||||
#include <boost/python/converter/registry.hpp>
|
||||
#include <boost/python/reference.hpp>
|
||||
#include <boost/cast.hpp>
|
||||
//#include <boost/mpl/type_list.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
namespace
|
||||
{
|
||||
// Only an object which we know is holding a char const* can be
|
||||
// converted to one
|
||||
struct convertible_to_cstring
|
||||
// An lvalue conversion function which extracts a char const* from a
|
||||
// Python String.
|
||||
void* convert_to_cstring(PyObject* obj)
|
||||
{
|
||||
static unaryfunc* execute(PyObject* obj)
|
||||
{
|
||||
return PyString_Check(obj) ? &obj->ob_type->tp_str : 0;
|
||||
}
|
||||
};
|
||||
return PyString_Check(obj) ? PyString_AsString(obj) : 0;
|
||||
}
|
||||
|
||||
struct extract_cstring
|
||||
// Given a target type and a SlotPolicy describing how to perform a
|
||||
// given conversion, registers from_python converters which use the
|
||||
// SlotPolicy to extract the type.
|
||||
template <class T, class SlotPolicy>
|
||||
struct slot_rvalue_from_python
|
||||
{
|
||||
static char const* execute(PyObject* obj)
|
||||
{
|
||||
return PyString_AsString(obj);
|
||||
}
|
||||
};
|
||||
|
||||
// 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
|
||||
{
|
||||
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;
|
||||
|
||||
public:
|
||||
tp_scalar_from_python()
|
||||
: from_python_converter<T>(
|
||||
&convertible_fn::execute
|
||||
, convert)
|
||||
{}
|
||||
|
||||
static T convert(PyObject* obj, from_python_data& data)
|
||||
slot_rvalue_from_python()
|
||||
{
|
||||
unaryfunc converter = *(unaryfunc*)data.stage1;
|
||||
ref converted(converter(obj));
|
||||
return TExtract::execute(converted.get());
|
||||
registry::insert(
|
||||
&slot_rvalue_from_python<T,SlotPolicy>::convertible
|
||||
, &slot_rvalue_from_python<T,SlotPolicy>::construct
|
||||
, undecorated_type_id<T>()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// 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 tp_cref_from_python<T,Convertible,TExtract> self;
|
||||
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)
|
||||
static void* convertible(PyObject* obj)
|
||||
{
|
||||
unaryfunc converter = *(unaryfunc*)data.stage1;
|
||||
|
||||
void* storage = self::get_storage(data);
|
||||
|
||||
ref converted(converter(obj));
|
||||
|
||||
T* const p = new (storage) T(TExtract::execute(converted.get()));
|
||||
|
||||
// note that construction is successful.
|
||||
data.stage1 = p;
|
||||
|
||||
return *p;
|
||||
unaryfunc* slot = SlotPolicy::get_slot(obj);
|
||||
return slot && *slot ? slot : 0;
|
||||
}
|
||||
|
||||
static void construct(PyObject* obj, rvalue_stage1_data* data)
|
||||
{
|
||||
// Get the (intermediate) source object
|
||||
unaryfunc creator = *static_cast<unaryfunc*>(data->convertible);
|
||||
ref intermediate(creator(obj));
|
||||
|
||||
// Get the location in which to construct
|
||||
void* storage = ((rvalue_data<T>*)data)->storage.bytes;
|
||||
new (storage) T(SlotPolicy::extract(intermediate.get()));
|
||||
|
||||
// record successful construction
|
||||
data->convertible = storage;
|
||||
}
|
||||
};
|
||||
|
||||
struct convertible_to_int
|
||||
// A SlotPolicy for extracting integer types from Python objects
|
||||
struct int_rvalue_from_python
|
||||
{
|
||||
static unaryfunc* execute(PyObject* obj)
|
||||
static unaryfunc* get_slot(PyObject* obj)
|
||||
{
|
||||
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
|
||||
// creating a new object. We'll handle that 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;
|
||||
return &number_methods->nb_int;
|
||||
}
|
||||
};
|
||||
|
||||
struct py_int_or_float_as_long
|
||||
{
|
||||
static long execute(PyObject* obj)
|
||||
|
||||
static long extract(PyObject* intermediate)
|
||||
{
|
||||
if (PyObject_TypeCheck(obj, &PyFloat_Type))
|
||||
if (PyObject_TypeCheck(intermediate, &PyFloat_Type))
|
||||
{
|
||||
return numeric_cast<long>(PyFloat_AS_DOUBLE(obj));
|
||||
return numeric_cast<long>(PyFloat_AS_DOUBLE(intermediate));
|
||||
}
|
||||
else
|
||||
{
|
||||
return PyInt_AS_LONG(obj);
|
||||
return PyInt_AS_LONG(intermediate);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// identity_unaryfunc/non_null -- manufacture a unaryfunc "slot"
|
||||
// which just returns its argument. Used for bool conversions, since
|
||||
// all Python objects are directly convertible to bool
|
||||
extern "C" PyObject* identity_unaryfunc(PyObject* x)
|
||||
{
|
||||
Py_INCREF(x);
|
||||
return x;
|
||||
}
|
||||
|
||||
unaryfunc non_null = identity_unaryfunc;
|
||||
|
||||
struct convertible_to_bool
|
||||
|
||||
// A SlotPolicy for extracting bool from a Python object
|
||||
struct bool_rvalue_from_python
|
||||
{
|
||||
static unaryfunc* execute(PyObject* obj)
|
||||
static unaryfunc* get_slot(PyObject*)
|
||||
{
|
||||
return &non_null;
|
||||
}
|
||||
};
|
||||
|
||||
struct py_object_as_bool
|
||||
{
|
||||
static bool execute(PyObject* obj)
|
||||
|
||||
static bool extract(PyObject* intermediate)
|
||||
{
|
||||
return PyObject_IsTrue(obj);
|
||||
return PyObject_IsTrue(intermediate);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct convertible_to_double
|
||||
// A SlotPolicy for extracting floating types from Python objects.
|
||||
struct float_rvalue_from_python
|
||||
{
|
||||
static unaryfunc* execute(PyObject* obj)
|
||||
static unaryfunc* get_slot(PyObject* obj)
|
||||
{
|
||||
PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
|
||||
if (number_methods == 0)
|
||||
@@ -189,67 +132,63 @@ namespace
|
||||
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;
|
||||
return &number_methods->nb_float;
|
||||
}
|
||||
};
|
||||
|
||||
struct py_float_or_int_as_double
|
||||
{
|
||||
static double execute(PyObject* obj)
|
||||
|
||||
static double extract(PyObject* intermediate)
|
||||
{
|
||||
if (PyObject_TypeCheck(obj, &PyInt_Type))
|
||||
if (PyObject_TypeCheck(intermediate, &PyInt_Type))
|
||||
{
|
||||
return PyInt_AS_LONG(obj);
|
||||
return PyInt_AS_LONG(intermediate);
|
||||
}
|
||||
else
|
||||
{
|
||||
return PyFloat_AS_DOUBLE(obj);
|
||||
return PyFloat_AS_DOUBLE(intermediate);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Convertible, class Convert>
|
||||
struct scalar_from_python
|
||||
// A SlotPolicy for extracting C++ strings from Python objects.
|
||||
struct string_rvalue_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;
|
||||
}
|
||||
}
|
||||
// If the underlying object is "string-able" this will succeed
|
||||
static unaryfunc* get_slot(PyObject* obj)
|
||||
{
|
||||
return &obj->ob_type->tp_str;
|
||||
};
|
||||
|
||||
#define REGISTER_INT_CONVERTERS(U) register_int_converters<U>()
|
||||
// Remember that this will be used to construct the result object
|
||||
static char const* extract(PyObject* intermediate)
|
||||
{
|
||||
return PyString_AsString(intermediate);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#define REGISTER_INT_CONVERTERS(U) slot_rvalue_from_python<U,int_rvalue_from_python>()
|
||||
#define REGISTER_INT_CONVERTERS2(U) REGISTER_INT_CONVERTERS(signed U); REGISTER_INT_CONVERTERS(unsigned U)
|
||||
|
||||
void initialize_builtin_converters()
|
||||
{
|
||||
static scalar_from_python<
|
||||
bool, convertible_to_bool, py_object_as_bool> bool_from_python;
|
||||
|
||||
// booleans
|
||||
slot_rvalue_from_python<bool,bool_rvalue_from_python>();
|
||||
|
||||
// integer types
|
||||
REGISTER_INT_CONVERTERS2(char);
|
||||
REGISTER_INT_CONVERTERS2(short);
|
||||
REGISTER_INT_CONVERTERS2(int);
|
||||
REGISTER_INT_CONVERTERS2(long);
|
||||
|
||||
static scalar_from_python<
|
||||
float,convertible_to_double,py_float_or_int_as_double> float_from_python;
|
||||
// floating types
|
||||
slot_rvalue_from_python<float,float_rvalue_from_python>();
|
||||
slot_rvalue_from_python<double,float_rvalue_from_python>();
|
||||
slot_rvalue_from_python<long double,float_rvalue_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;
|
||||
// Add an lvalue converter for char which gets us char const*
|
||||
registry::insert(convert_to_cstring,undecorated_type_id<char>());
|
||||
|
||||
static tp_cref_from_python<
|
||||
std::string, convertible_to_string, extract_cstring> string_from_python;
|
||||
// Register by-value converters to std::string
|
||||
slot_rvalue_from_python<std::string, string_rvalue_from_python>();
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
@@ -4,23 +4,40 @@
|
||||
// "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>
|
||||
#include <boost/python/converter/registry.hpp>
|
||||
#include <boost/python/converter/find_from_python.hpp>
|
||||
#include <boost/python/converter/registrations.hpp>
|
||||
#include <boost/python/converter/from_python_data.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)
|
||||
|
||||
BOOST_PYTHON_DECL void* find(
|
||||
PyObject* source
|
||||
, rvalue_from_python_registration const* chain
|
||||
, rvalue_stage1_data& data)
|
||||
{
|
||||
// Insert this in the converter chain.
|
||||
from_python_converter_base*& head = registry::from_python_chain(type);
|
||||
m_next = head;
|
||||
head = this;
|
||||
for (;chain != 0; chain = chain->next)
|
||||
{
|
||||
void* r = chain->convertible(source);
|
||||
if (r != 0)
|
||||
{
|
||||
data.construct = chain->construct;
|
||||
return data.convertible = r;
|
||||
}
|
||||
}
|
||||
return data.convertible = 0;
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL void* find(
|
||||
PyObject* const source
|
||||
, lvalue_from_python_registration const* chain)
|
||||
{
|
||||
for (;chain != 0; chain = chain->next)
|
||||
{
|
||||
void* r = chain->convert(source);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
@@ -1,35 +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.
|
||||
#include <boost/python/converter/handle.hpp>
|
||||
#include <boost/python/converter/body.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
bool handle::convertible() const
|
||||
{
|
||||
for (handle const* p = this; p != 0; p = p->m_next)
|
||||
{
|
||||
if (p->m_body == 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void handle::destroy()
|
||||
{
|
||||
// Recurse down the chain releasing from tail to head
|
||||
if (m_next != 0)
|
||||
m_next->destroy();
|
||||
|
||||
// Our body knows how to destroy us. If we never got a body,
|
||||
// there's nothing to do.
|
||||
if (m_body)
|
||||
m_body->destroy_handle(this);
|
||||
}
|
||||
|
||||
// void handle::dummy::nonnull() {}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
@@ -4,6 +4,7 @@
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#include <boost/python/converter/registry.hpp>
|
||||
#include <boost/python/converter/registrations.hpp>
|
||||
#include <boost/python/converter/builtin_converters.hpp>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
@@ -19,20 +20,23 @@ namespace // <unnamed>
|
||||
|
||||
// The unique to_python converter for the associated C++ type.
|
||||
to_python_value_function m_to_python_converter;
|
||||
|
||||
|
||||
// The collection of from_python converters for the associated
|
||||
// C++ type.
|
||||
from_python_converter_base* m_from_python_converters;
|
||||
lvalue_from_python_registration* m_lvalue_from_python;
|
||||
rvalue_from_python_registration* m_rvalue_from_python;
|
||||
|
||||
// The class object associated with this type
|
||||
PyTypeObject* m_class_object;
|
||||
};
|
||||
|
||||
typedef std::map<type_id_t, entry> registry_t;
|
||||
typedef std::map<undecorated_type_id_t, entry> registry_t;
|
||||
|
||||
registry_t& entries()
|
||||
{
|
||||
static registry_t registry;
|
||||
|
||||
#ifdef BOOST_PYTHON_DYNAMIC_LIB // this conditional should go away eventually.
|
||||
static bool builtin_converters_initialized = false;
|
||||
if (!builtin_converters_initialized)
|
||||
{
|
||||
@@ -42,17 +46,19 @@ namespace // <unnamed>
|
||||
|
||||
initialize_builtin_converters();
|
||||
}
|
||||
#endif
|
||||
return registry;
|
||||
}
|
||||
|
||||
entry* find(type_id_t type)
|
||||
entry* find(undecorated_type_id_t type)
|
||||
{
|
||||
return &entries()[type];
|
||||
}
|
||||
|
||||
entry::entry()
|
||||
: m_to_python_converter(0)
|
||||
, m_from_python_converters(0)
|
||||
, m_lvalue_from_python(0)
|
||||
, m_rvalue_from_python(0)
|
||||
, m_class_object(0)
|
||||
{
|
||||
}
|
||||
@@ -78,15 +84,46 @@ namespace registry
|
||||
slot = f;
|
||||
}
|
||||
|
||||
from_python_converter_base*& from_python_chain(type_id_t key)
|
||||
// Insert an lvalue from_python converter
|
||||
void insert(void* (*convert)(PyObject*), undecorated_type_id_t key)
|
||||
{
|
||||
return find(key)->m_from_python_converters;
|
||||
entry* found = find(key);
|
||||
lvalue_from_python_registration *registration = new lvalue_from_python_registration;
|
||||
registration->convert = convert;
|
||||
registration->next = found->m_lvalue_from_python;
|
||||
found->m_lvalue_from_python = registration;
|
||||
|
||||
insert(convert, 0, key);
|
||||
}
|
||||
|
||||
|
||||
// Insert an rvalue from_python converter
|
||||
void insert(void* (*convertible)(PyObject*)
|
||||
, constructor_function construct
|
||||
, undecorated_type_id_t key)
|
||||
{
|
||||
entry* found = find(key);
|
||||
rvalue_from_python_registration *registration = new rvalue_from_python_registration;
|
||||
registration->convertible = convertible;
|
||||
registration->construct = construct;
|
||||
registration->next = found->m_rvalue_from_python;
|
||||
found->m_rvalue_from_python = registration;
|
||||
}
|
||||
|
||||
PyTypeObject*& class_object(undecorated_type_id_t key)
|
||||
{
|
||||
return find(key)->m_class_object;
|
||||
}
|
||||
|
||||
lvalue_from_python_registration*& lvalue_converters(undecorated_type_id_t key)
|
||||
{
|
||||
return find(key)->m_lvalue_from_python;
|
||||
}
|
||||
|
||||
rvalue_from_python_registration*& rvalue_converters(undecorated_type_id_t key)
|
||||
{
|
||||
return find(key)->m_rvalue_from_python;
|
||||
}
|
||||
|
||||
} // namespace registry
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
@@ -1,36 +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.
|
||||
|
||||
#include <boost/python/converter/unwrap.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
namespace
|
||||
{
|
||||
struct pyobject_unwrapper : unwrapper_base
|
||||
{
|
||||
pyobject_unwrapper();
|
||||
void* can_convert(PyObject*) const;
|
||||
};
|
||||
|
||||
pyobject_unwrapper static_unwrapper;
|
||||
std::pair<unwrapper_base*,void*> unwrapper_pair(&static_unwrapper,&static_unwrapper);
|
||||
|
||||
pyobject_unwrapper::pyobject_unwrapper()
|
||||
: unwrapper_base(type_id<PyObject*>())
|
||||
{
|
||||
}
|
||||
|
||||
void* pyobject_unwrapper::can_convert(PyObject*) const
|
||||
{
|
||||
return non_null;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL std::pair<unwrapper_base*,void*>&
|
||||
unwrap_more_<PyObject*>::m_unwrapper = unwrapper_pair;
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
@@ -1,31 +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.
|
||||
#include <boost/python/converter/unwrapper.hpp>
|
||||
#include <boost/python/converter/registry.hpp>
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
unwrapper_base::unwrapper_base(type_id_t key)
|
||||
: body(key)
|
||||
{
|
||||
registry::insert(*this);
|
||||
}
|
||||
|
||||
unwrapper_base::~unwrapper_base()
|
||||
{
|
||||
if (can_unregister())
|
||||
registry::remove(*this);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
int arbitrary;
|
||||
}
|
||||
|
||||
void* const unwrapper_base::non_null = &arbitrary;
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
@@ -1,41 +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.
|
||||
|
||||
#include <boost/python/converter/registry.hpp>
|
||||
#include <boost/python/converter/wrapper.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
wrapper_base::wrapper_base(type_id_t type)
|
||||
: body(type)
|
||||
{
|
||||
registry::insert(*this);
|
||||
}
|
||||
|
||||
wrapper_base::~wrapper_base()
|
||||
{
|
||||
if (can_unregister())
|
||||
registry::remove(*this);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// This doesn't actually get called, but we need something to fill
|
||||
// in the slot in the wrap<PyObject*> class.
|
||||
struct identity_wrapper_t : wrapper<PyObject*>
|
||||
{
|
||||
PyObject* convert(PyObject* source) const
|
||||
{
|
||||
return source;
|
||||
}
|
||||
};
|
||||
|
||||
identity_wrapper_t identity_wrapper_object;
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL body& identity_wrapper = identity_wrapper_object;
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
@@ -163,7 +163,7 @@ void instance_holder::install(PyObject* self) throw()
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL void*
|
||||
find_instance_impl(PyObject* inst, converter::type_id_t type)
|
||||
find_instance_impl(PyObject* inst, converter::undecorated_type_id_t type)
|
||||
{
|
||||
if (inst->ob_type->ob_type != &class_metatype_object)
|
||||
return 0;
|
||||
|
||||
81
test/destroy_test.cpp
Normal file
81
test/destroy_test.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#include <boost/python/detail/destroy.hpp>
|
||||
#include <cassert>
|
||||
|
||||
struct bar;
|
||||
|
||||
namespace boost
|
||||
{
|
||||
// lie to the library about bar so we can show that it's destructor is optimized away.
|
||||
template <>
|
||||
struct has_trivial_destructor<bar>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value=true);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
int count;
|
||||
int marks[] = {
|
||||
-1
|
||||
, -1, -1
|
||||
, -1, -1, -1, -1
|
||||
, -1
|
||||
};
|
||||
int* kills = marks;
|
||||
|
||||
struct foo
|
||||
{
|
||||
foo() : n(count++) {}
|
||||
~foo()
|
||||
{
|
||||
*kills++ = n;
|
||||
}
|
||||
int n;
|
||||
};
|
||||
|
||||
struct bar : foo {};
|
||||
|
||||
void assert_destructions(int n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
assert(marks[i] == i);
|
||||
assert(marks[n] == -1);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
assert_destructions(0);
|
||||
typedef int a[2];
|
||||
|
||||
foo* f1 = new foo;
|
||||
boost::python::detail::destroy_reference<foo const volatile&>(f1);
|
||||
assert_destructions(1);
|
||||
|
||||
foo* f2 = new foo[2];
|
||||
typedef foo x[2];
|
||||
|
||||
boost::python::detail::destroy_reference<x const&>(f2);
|
||||
assert_destructions(3);
|
||||
|
||||
typedef foo y[2][2];
|
||||
x* f3 = new y;
|
||||
boost::python::detail::destroy_reference<y&>(f3);
|
||||
assert_destructions(7);
|
||||
|
||||
bar* b1 = new bar;
|
||||
boost::python::detail::destroy_reference<bar&>(b1);
|
||||
assert_destructions(7);
|
||||
|
||||
bar* b2 = new bar[2];
|
||||
typedef bar xb[2];
|
||||
|
||||
boost::python::detail::destroy_reference<xb&>(b2);
|
||||
assert_destructions(7);
|
||||
|
||||
typedef bar yb[2][2];
|
||||
xb* b3 = new yb;
|
||||
boost::python::detail::destroy_reference<yb&>(b3);
|
||||
assert_destructions(7);
|
||||
|
||||
return 0;
|
||||
}
|
||||
48
test/indirect_traits_test.cpp
Normal file
48
test/indirect_traits_test.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
//#include <stdio.h>
|
||||
#include <cassert>
|
||||
#include <boost/python/detail/indirect_traits.hpp>
|
||||
|
||||
//#define print(expr) printf("%s ==> %s\n", #expr, expr)
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::python::detail;
|
||||
|
||||
assert(is_reference_to_pointer<int*&>::value);
|
||||
assert(is_reference_to_pointer<int* const&>::value);
|
||||
assert(is_reference_to_pointer<int*volatile&>::value);
|
||||
assert(is_reference_to_pointer<int*const volatile&>::value);
|
||||
|
||||
assert(!is_reference_to_pointer<int const volatile>::value);
|
||||
assert(!is_reference_to_pointer<int>::value);
|
||||
assert(!is_reference_to_pointer<int*>::value);
|
||||
|
||||
assert(!is_reference_to_const<int*&>::value);
|
||||
assert(is_reference_to_const<int* const&>::value);
|
||||
assert(!is_reference_to_const<int*volatile&>::value);
|
||||
assert(is_reference_to_const<int*const volatile&>::value);
|
||||
|
||||
assert(!is_reference_to_const<int const volatile>::value);
|
||||
assert(!is_reference_to_const<int>::value);
|
||||
assert(!is_reference_to_const<int*>::value);
|
||||
|
||||
assert(is_reference_to_non_const<int*&>::value);
|
||||
assert(!is_reference_to_non_const<int* const&>::value);
|
||||
assert(is_reference_to_non_const<int*volatile&>::value);
|
||||
assert(!is_reference_to_non_const<int*const volatile&>::value);
|
||||
|
||||
assert(!is_reference_to_non_const<int const volatile>::value);
|
||||
assert(!is_reference_to_non_const<int>::value);
|
||||
assert(!is_reference_to_non_const<int*>::value);
|
||||
|
||||
assert(!is_reference_to_volatile<int*&>::value);
|
||||
assert(!is_reference_to_volatile<int* const&>::value);
|
||||
assert(is_reference_to_volatile<int*volatile&>::value);
|
||||
assert(is_reference_to_volatile<int*const volatile&>::value);
|
||||
|
||||
assert(!is_reference_to_volatile<int const volatile>::value);
|
||||
assert(!is_reference_to_volatile<int>::value);
|
||||
assert(!is_reference_to_volatile<int*>::value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
51
test/m1.cpp
51
test/m1.cpp
@@ -9,15 +9,13 @@
|
||||
#include "complicated.hpp"
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/type_from_python.hpp>
|
||||
#include <boost/python/object/value_holder.hpp>
|
||||
#include <boost/python/object/pointer_holder.hpp>
|
||||
#include <boost/python/object/class.hpp>
|
||||
#include <boost/python/copy_const_reference.hpp>
|
||||
#include <boost/python/return_value_policy.hpp>
|
||||
#include <boost/python/converter/class.hpp>
|
||||
#include <boost/python/lvalue_from_python.hpp>
|
||||
#include <boost/python/to_python_converter.hpp>
|
||||
#include <boost/python/value_from_python.hpp>
|
||||
#include <boost/python/errors.hpp>
|
||||
#include <boost/mpl/type_list.hpp>
|
||||
#include <string.h>
|
||||
@@ -105,7 +103,6 @@ PyObject* new_simple()
|
||||
// description of how the type parameters to wrapper<> and unwrapper<>
|
||||
// are selected.
|
||||
//
|
||||
using boost::python::converter::from_python_data;
|
||||
using boost::python::to_python_converter;
|
||||
|
||||
// Wrap a simple by copying it into a Simple
|
||||
@@ -120,16 +117,13 @@ struct simple_to_python
|
||||
}
|
||||
};
|
||||
|
||||
int noddy_to_int(PyObject* p, from_python_data&)
|
||||
struct int_from_noddy_extractor
|
||||
{
|
||||
return static_cast<NoddyObject*>(p)->x;
|
||||
}
|
||||
|
||||
// Extract a mutable reference to an int from a Noddy.
|
||||
int& noddy_to_int_ref(PyObject* p, from_python_data&)
|
||||
{
|
||||
return static_cast<NoddyObject*>(p)->x;
|
||||
}
|
||||
static int& execute(NoddyObject& p)
|
||||
{
|
||||
return p.x;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Some C++ functions to expose to Python
|
||||
@@ -205,40 +199,23 @@ D take_d(D const& d) { return d; }
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(m1)
|
||||
{
|
||||
using boost::python::module;
|
||||
using boost::python::class_;
|
||||
using boost::python::converter::from_python_converter;
|
||||
using boost::python::lvalue_from_python;
|
||||
using boost::python::value_from_python;
|
||||
using boost::python::type_from_python;
|
||||
using boost::python::get_member;
|
||||
using boost::python::copy_const_reference;
|
||||
using boost::python::return_value_policy;
|
||||
using namespace boost::python;
|
||||
using boost::mpl::type_list;
|
||||
|
||||
// Create the converters; they are self-registering/unregistering.
|
||||
static simple_to_python c1;
|
||||
simple_to_python();
|
||||
|
||||
static from_python_converter<int> c2(
|
||||
&(boost::python::type_from_python<&NoddyType>::convertible), noddy_to_int);
|
||||
|
||||
static from_python_converter<int&> c3(
|
||||
&(boost::python::type_from_python<&NoddyType>::convertible), noddy_to_int_ref);
|
||||
type_from_python<&NoddyType,int_from_noddy_extractor>();
|
||||
|
||||
static boost::python::lvalue_from_python<
|
||||
boost::python::type_from_python<
|
||||
&SimpleType
|
||||
, simple
|
||||
, SimpleObject
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
, boost::python::get_member<SimpleObject, simple, &SimpleObject::x>
|
||||
, member_extractor<SimpleObject, simple, &SimpleObject::x>
|
||||
#else
|
||||
, extract_simple_object
|
||||
#endif
|
||||
>
|
||||
unwrap_simple;
|
||||
>();
|
||||
|
||||
static boost::python::lvalue_from_python<&SimpleType, SimpleObject>
|
||||
unwrap_simple2;
|
||||
type_from_python<&SimpleType, identity_extractor<SimpleObject> >();
|
||||
|
||||
module m1("m1");
|
||||
|
||||
|
||||
39
test/pointer_type_id_test.cpp
Normal file
39
test/pointer_type_id_test.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <boost/python/converter/type_id.hpp>
|
||||
#include <cassert>
|
||||
#include <boost/python/converter/pointer_type_id.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace boost::python::converter;
|
||||
|
||||
undecorated_type_id_t x
|
||||
= undecorated_type_id<int>();
|
||||
|
||||
|
||||
assert(pointer_type_id<int*>() == x);
|
||||
assert(pointer_type_id<int const*>() == x);
|
||||
assert(pointer_type_id<int volatile*>() == x);
|
||||
assert(pointer_type_id<int const volatile*>() == x);
|
||||
|
||||
assert(pointer_type_id<int*&>() == x);
|
||||
assert(pointer_type_id<int const*&>() == x);
|
||||
assert(pointer_type_id<int volatile*&>() == x);
|
||||
assert(pointer_type_id<int const volatile*&>() == x);
|
||||
|
||||
assert(pointer_type_id<int*const&>() == x);
|
||||
assert(pointer_type_id<int const*const&>() == x);
|
||||
assert(pointer_type_id<int volatile*const&>() == x);
|
||||
assert(pointer_type_id<int const volatile*const&>() == x);
|
||||
|
||||
assert(pointer_type_id<int*volatile&>() == x);
|
||||
assert(pointer_type_id<int const*volatile&>() == x);
|
||||
assert(pointer_type_id<int volatile*volatile&>() == x);
|
||||
assert(pointer_type_id<int const volatile*volatile&>() == x);
|
||||
|
||||
assert(pointer_type_id<int*const volatile&>() == x);
|
||||
assert(pointer_type_id<int const*const volatile&>() == x);
|
||||
assert(pointer_type_id<int volatile*const volatile&>() == x);
|
||||
assert(pointer_type_id<int const volatile*const volatile&>() == x);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user