2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-23 05:42:30 +00:00

Last rewrite of the type conversion mechanism, I hope

[SVN r12631]
This commit is contained in:
Dave Abrahams
2002-02-02 14:04:48 +00:00
parent 12988b879e
commit 25c56164b0
29 changed files with 305 additions and 916 deletions

View File

@@ -15,7 +15,6 @@ PYTHON_PROPERTIES
dll bpl
:
src/converter/from_python.cpp
src/converter/to_python.cpp
src/converter/registry.cpp
src/converter/type_id.cpp
src/object/class.cpp

View File

@@ -1,50 +0,0 @@
#include <iostream>
#include <string>
namespace { // Avoid cluttering the global namespace.
// A friendly class.
class world
{
private:
std::string country;
public:
world(const std::string& country) { this->country = country; }
std::string greet() const { return "Hello from " + country + "!"; }
};
// A function taking a world object as an argument.
std::string invite(const world& w) {
return w.greet() + " Please come soon!";
}
}
#include <py_cpp/class_wrapper.h>
// Python requires an exported function called init<module-name> in every
// extension module. This is where we build the module contents.
BOOST_PYTHON_MODULE_INIT(example2)
{
// Create an object representing this extension module.
py::Module this_module("example2");
// Create the Python type object for our extension class.
py::ClassWrapper<world> world_class(this_module, "world");
// Add the __init__ function.
world_class.def(py::Constructor<std::string>());
// Add a regular member function.
world_class.def(&world::greet, "greet");
// Add invite() as a regular function to the module.
this_module.def(invite, "invite");
// Even better, invite() can also be made a member of world_class!!!
world_class.def(invite, "invite");
}
// Win32 DLL boilerplate
#if defined(_WIN32)
#include <windows.h>
extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return 1; }
#endif // _WIN32

View File

@@ -1,101 +0,0 @@
#include <py_cpp/class_wrapper.h>
#include <py_cpp/objects.h>
#define rangei(n) for (int i = 0; i < n; i++)
namespace { // Avoid cluttering the global namespace.
// A wrapper is used to define additional constructors.
//
struct vector_double_wrapper: std::vector<double>
{
// Tell the compiler how to convert a base class object to
// this wrapper object.
vector_double_wrapper(PyObject*, const std::vector<double>& vd)
: std::vector<double>(vd) {}
vector_double_wrapper(PyObject* self)
: std::vector<double>() {}
vector_double_wrapper(PyObject* self, const int n)
: std::vector<double>(n) {}
vector_double_wrapper(PyObject* self, py::Tuple tuple)
: std::vector<double>(tuple.size())
{
std::vector<double>::iterator vd = begin();
rangei(tuple.size())
vd[i] = from_python(tuple[i].get(), py::Type<double>()); // GCC BUG
}
};
double getitem(const std::vector<double>& vd, const std::size_t key) {
return vd[key];
}
void setitem(std::vector<double>& vd, const std::size_t key,
const double &d) {
std::vector<double>::iterator vditer = vd.begin();
vditer[key] = d;
}
void delitem(std::vector<double>& vd, const std::size_t key) {
std::vector<double>::iterator vditer = vd.begin();
vd.erase(&vditer[key]);
}
// Convert vector_double to a regular Python tuple.
//
py::Tuple as_tuple(const std::vector<double>& vd)
{
py::Tuple t(vd.size());
rangei(vd.size()) t.set_item(i, py::Ptr(py::to_python(vd[i]))); // GCC BUG
return t;
}
// Function returning a vector_double object to Python.
//
std::vector<double> foo(const int n)
{
std::vector<double> vd(n);
std::vector<double>::iterator vditer = vd.begin();
rangei(n) vditer[i] = double(i);
return vd;
}
// Same as foo(), but avoid copying on return.
//
std::auto_ptr<std::vector<double> > bar(const int n)
{
std::auto_ptr<std::vector<double> > vdptr(new std::vector<double>(n));
std::vector<double>::iterator vditer = vdptr->begin();
rangei(n) vditer[i] = double(10 * i);
return vdptr;
}
}
BOOST_PYTHON_MODULE_INIT(example3)
{
py::Module this_module("example3");
py::ClassWrapper<std::vector<double>, vector_double_wrapper>
vector_double(this_module, "vector_double");
vector_double.def(py::Constructor<>());
vector_double.def(py::Constructor<const int>());
vector_double.def(py::Constructor<py::Tuple>());
vector_double.def(&std::vector<double>::size, "__len__");
vector_double.def(getitem, "__getitem__");
vector_double.def(setitem, "__setitem__");
vector_double.def(delitem, "__delitem__");
vector_double.def(as_tuple, "as_tuple");
this_module.def(foo, "foo");
this_module.def(bar, "bar");
}
// Win32 DLL boilerplate
#if defined(_WIN32)
#include <windows.h>
extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return 1; }
#endif // _WIN32

View File

@@ -8,20 +8,41 @@
# include <string>
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python { namespace converter {
namespace boost { namespace python {
template <class T> struct to_python_lookup;
// Provide specializations of to_python_value
template <class T> struct to_python_value;
template <class T>
struct to_python_int
namespace detail
{
bool convertible() const { return true; }
PyObject* operator()(T x) const { return PyInt_FromLong(long(x)); }
};
struct builtin_to_python
{
static bool convertible() { return true; }
};
}
# 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&> {};
# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \
template <> struct to_python_value<T&> \
: detail::builtin_to_python \
{ \
PyObject* operator()(T const& x) const \
{ \
return (expr); \
} \
}; \
template <> struct to_python_value<T const&> \
: detail::builtin_to_python \
{ \
PyObject* operator()(T const& x) const \
{ \
return (expr); \
} \
};
# define BOOST_PYTHON_TO_INT(T) \
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, PyInt_FromLong(x)) \
BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned T, PyInt_FromLong(x))
BOOST_PYTHON_TO_INT(char)
BOOST_PYTHON_TO_INT(short)
@@ -29,47 +50,13 @@ 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());
}
};
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, PyString_FromString(x))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, PyString_FromString(x.c_str()))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x))
BOOST_PYTHON_TO_PYTHON_BY_VALUE(PyObject*, x)
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
}} // namespace boost::python::converter
#endif // BUILTIN_TO_PYTHON_CONVERTERS_DWA2002129_HPP

View File

@@ -11,7 +11,7 @@
# 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/converter/registry.hpp>
# include <boost/python/detail/wrap_python.hpp>
namespace boost { namespace python { namespace converter {
@@ -29,16 +29,21 @@ template <class T> struct from_python_lookup;
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;
// 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);
private:
// type_id_t m_key;
from_python_check m_convertible;
from_python_converter_base* m_next;
};
@@ -52,17 +57,24 @@ struct from_python_converter : from_python_converter_base
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;
};
// -------------------------------------------------------------------------
// Initialized to refer to a common place in the registry.
template <class T>
from_python_converter_base*const&
from_python_converter<T>::chain = registry::from_python_chain(type_id<T>());
//struct from_python_base
//{
//};
// -------------------------------------------------------------------------
// A class which implements from_python with a registry lookup.
template <class T>
@@ -95,12 +107,21 @@ 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
inline from_python_converter_base const*
from_python_converter_base::find(
from_python_converter_base const* chain, PyObject* p, void*& data)
{
return m_key;
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;
}
# endif
template <class T>
inline from_python_converter<T>::from_python_converter(
@@ -115,6 +136,14 @@ inline from_python_converter<T>::from_python_converter(
}
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
{
@@ -133,7 +162,7 @@ inline void from_python_converter<T>::destroy(from_python_data& data) const
template <class T>
inline from_python_lookup<T>::from_python_lookup(PyObject* src)
: m_converter(
registration<T>::get_from_python(
from_python_converter<T>::find(
src, m_intermediate_data.stage1))
{
}

View File

@@ -1,148 +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 REGISTRATION_DWA20011130_HPP
# define REGISTRATION_DWA20011130_HPP
# include <boost/python/detail/config.hpp>
# include <boost/python/converter/registry.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/detail/config.hpp>
# include <boost/mpl/pop_front.hpp>
# include <boost/mpl/for_each.hpp>
# include <boost/mpl/front.hpp>
# include <utility>
# ifdef BOOST_PYTHON_TRACE
# include <iostream>
# endif
namespace boost { namespace python { namespace converter {
template <class T> struct from_python_converter;
template <class T> struct target;
template <class T> struct source;
// This class is really sort of a "templated namespace". It manages a
// static data member which refers to the registry entry for T. This
// reference is acquired once to reduce the burden of multiple
// dictionary lookups at runtime.
template <class T>
struct registration
{
public: // member functions
// Return a converter which can convert the given Python object to
// T, or 0 if no such converter exists. Fill in data with
// the result of the converter's check function
static from_python_converter<T> const* get_from_python(PyObject*, void*& data);
// Return a converter which can convert T to a Python object, or 0
// if no such converter exists
static to_python_function<T>::type get_to_python();
static registry::entry* find_entry();
private: // helper functions
static registry::entry* entry();
static registry::entry* known_entry();
private: // data members
static registry::entry* m_registry_entry;
};
namespace detail
{
// An MPL BinaryMetaFunction class which initializes the
// registration entry for the target type of its 2nd argument.
struct setup_target_registration
{
template <class Ignored, class T> struct apply
{
typedef T type;
static void execute()
{
typedef typename target<T>::type target_t;
registration<target_t>::find_entry();
}
};
};
template <class T>
struct find_return_value_entry
{
static void execute() { registration<T>::find_entry(); }
};
template <>
struct find_return_value_entry<void>
{
static void execute() {}
};
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1200
template <>
struct find_return_value_entry<void const>
{
static void execute() {}
};
# endif
}
template <class Sequence>
void acquire_registrations(Sequence signature)
{
typedef typename mpl::pop_front<Sequence>::sequence args;
typedef typename mpl::front<Sequence>::type return_type;
mpl::for_each<args, void, detail::setup_target_registration>::execute();
typedef typename source<return_type>::type return_source_type;
detail::find_return_value_entry<return_source_type>::execute();
}
// because this is static POD data it will be initialized to zero
template <class T>
registry::entry* registration<T>::m_registry_entry;
template <class T>
registry::entry* registration<T>::find_entry()
{
return m_registry_entry = registry::find(type_id<T>());
}
template <class T>
inline registry::entry* registration<T>::entry()
{
if (!m_registry_entry)
find_entry();
return m_registry_entry;
}
template <class T>
inline registry::entry* registration<T>::known_entry()
{
assert(m_registry_entry != 0);
return m_registry_entry;
}
template <class T>
from_python_converter<T> const* registration<T>::get_from_python(PyObject* p, void*& data)
{
return static_cast<from_python_converter<T> const*>(
known_entry()->get_from_python(p, data)
);
}
template <class T>
typename to_python_function<T>::type registration<T>::get_to_python()
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "retrieving wrapper for " << type_id<T>() << std::endl;
# endif
return reinterpret_cast<to_python_function<T>::type>(
known_entry()->get_to_python());
}
}}} // namespace boost::python::converter
#endif // REGISTRATION_DWA20011130_HPP

View File

@@ -5,72 +5,26 @@
// to its suitability for any purpose.
#ifndef REGISTRY_DWA20011127_HPP
# define REGISTRY_DWA20011127_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/converter/type_id.hpp>
# include <boost/python/detail/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/converter/to_python_function.hpp>
# include <vector>
# include <memory>
# include <utility>
namespace boost { namespace python { namespace converter {
struct BOOST_PYTHON_DECL from_python_converter_base;
struct BOOST_PYTHON_DECL to_python_converter_base;
// This namespace acts as a sort of singleton
namespace registry
{
// These are the elements stored in the registry
class BOOST_PYTHON_DECL entry
{
public: // member functions
entry();
~entry();
// Return a converter appropriate for converting the given
// Python object from_python to the C++ type with which this
// converter is associated in the registry, or 0 if no such
// converter exists.
from_python_converter_base const* get_from_python(PyObject*, void*& data) const;
// Return a conversion function appropriate for converting a C++
// object whose type this entry is associated with in the
// registry to a Python object, or 0 if no such converter
// exists. This function must be reinterpret_cast to the
// appropriate to_python_function type.
to_python_function_base get_to_python() const;
// Conversion classes use these functions to register
// themselves.
void insert(from_python_converter_base&);
void remove(from_python_converter_base&);
void insert(to_python_converter_base&);
void remove(to_python_converter_base&);
private: // types
typedef std::vector<from_python_converter_base*> from_python_converters;
private: // helper functions
from_python_converters::iterator find(from_python_converter_base const&);
private: // data members
// The collection of from_python converters for the associated
// C++ type.
from_python_converters m_from_python_converters;
// The unique to_python converter for the associated C++ type.
to_python_converter_base* m_to_python_converter;
};
BOOST_PYTHON_DECL entry* find(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_converter_base& x);
BOOST_PYTHON_DECL void insert(from_python_converter_base& x);
BOOST_PYTHON_DECL void remove(to_python_converter_base& x);
BOOST_PYTHON_DECL void remove(from_python_converter_base& x);
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);
BOOST_PYTHON_DECL PyTypeObject*& class_object(undecorated_type_id_t key);
}
}}} // namespace boost::python::converter

View File

@@ -1,32 +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 SOURCE_DWA20011119_HPP
# define SOURCE_DWA20011119_HPP
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/transform_traits.hpp>
# include <boost/mpl/select_type.hpp>
namespace boost { namespace python { namespace converter {
// source --
//
// This type generator (see
// ../../../more/generic_programming.html#type_generator) is used
// to select the argument type to use when converting T to a PyObject*
template <class T>
struct source
{
typedef
typename add_reference<
typename add_const<T>::type
>::type
type;
};
}}} // namespace boost::python::converter
#endif // SOURCE_DWA20011119_HPP

View File

@@ -1,24 +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 SOURCE_HOLDER_DWA20011215_HPP
# define SOURCE_HOLDER_DWA20011215_HPP
namespace boost { namespace python { namespace converter {
struct source_holder_base
{
};
template <class T>
struct source_holder : source_holder_base
{
source_holder(T x) : value(x) {}
T value;
};
}}} // namespace boost::python::converter
#endif // SOURCE_HOLDER_DWA20011215_HPP

View File

@@ -1,116 +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 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_convert != 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

@@ -7,15 +7,24 @@
# define TO_PYTHON_FUNCTION_DWA2002128_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/type_traits/transform_traits.hpp>
namespace boost { namespace python { namespace converter {
typedef PyObject* (*to_python_function_base)(void);
// The type of stored function pointers which actually do conversion
// by-value. The void* points to the object to be converted, and
// type-safety is preserved through runtime registration.
typedef PyObject* (*to_python_value_function)(void const*);
template <class T>
struct to_python_function
// Given a typesafe to_python conversion function, produces a
// to_python_value_function which can be registered in the usual way.
template <class T, class ToPython>
struct as_to_python_value_function
{
typedef PyObject*(*type)(T);
static PyObject* convert(void const* x)
{
return ToPython::convert(*(T const*)x);
}
};
}}} // namespace boost::python::converter

View File

@@ -7,8 +7,12 @@
# define TYPE_ID_DWA20011127_HPP
# include <boost/python/detail/config.hpp>
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/python/detail/msvc_typeinfo.hpp>
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/composite_traits.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/operators.hpp>
# include <boost/type.hpp>
# include <typeinfo>
# include <iosfwd>
# include <cstring>
@@ -16,13 +20,6 @@
namespace boost { namespace python { namespace converter {
// a portable mechanism for identifying types at runtime across modules.
namespace detail
{
template <class T> class dummy;
}
// for this compiler at least, cross-shared-library type_info
// comparisons don't work, so use typeid(x).name() instead. It's not
// yet clear what the best default strategy is.
@@ -61,7 +58,7 @@ struct type_id_t : totally_ordered<type_id_t>
{
enum decoration { const_ = 0x1, volatile_ = 0x2, reference = 0x4 };
type_id_t(undecorated_type_id_t, decoration decoration);
type_id_t(undecorated_type_id_t, decoration = decoration());
bool operator<(type_id_t const& rhs) const;
bool operator==(type_id_t const& rhs) const;
@@ -78,13 +75,19 @@ struct type_id_t : totally_ordered<type_id_t>
};
template <class T>
inline undecorated_type_id_t undecorated_type_id(detail::dummy<T>* = 0)
inline undecorated_type_id_t undecorated_type_id(boost::type<T>* = 0)
{
return undecorated_type_id_t(typeid(T));
return undecorated_type_id_t(
# if (!defined(BOOST_MSVC) || BOOST_MSVC > 1300) && (!defined(BOOST_INTEL_CXX_VERSION) || BOOST_INTEL_CXX_VERSION > 600)
typeid(T)
# else // strip the decoration which msvc and Intel mistakenly leave in
python::detail::msvc_typeid<T>()
# endif
);
}
template <class T>
inline type_id_t type_id(detail::dummy<T>* = 0)
inline type_id_t type_id(boost::type<T>* = 0)
{
return type_id_t(
undecorated_type_id<T>()

View File

@@ -1,28 +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 WRAPPER_BASE_DWA2002110_HPP
# define WRAPPER_BASE_DWA2002110_HPP
# include <boost/python/detail/wrap_python.hpp>
# include <boost/python/converter/body.hpp>
namespace boost { namespace python { namespace converter {
struct source_holder_base;
struct wrap_base;
template <class T> struct wrap_more_;
struct BOOST_PYTHON_DECL wrapper_base : body
{
public:
wrapper_base(type_id_t); // registers
~wrapper_base(); // unregisters
virtual PyObject* do_conversion(wrap_base const&, source_holder_base const&) const = 0;
};
}}} // namespace boost::python::converter
#endif // WRAPPER_BASE_DWA2002110_HPP

View File

@@ -7,7 +7,7 @@
# define COPY_CONST_REFERENCE_DWA2002131_HPP
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/python/to_python.hpp>
# include <boost/python/to_python_value.hpp>
namespace boost { namespace python {

View File

@@ -7,7 +7,7 @@
# define COPY_NON_CONST_REFERENCE_DWA2002131_HPP
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/mpl/select_type.hpp>
# include <boost/python/to_python.hpp>
# include <boost/python/to_python_value.hpp>
namespace boost { namespace python {

View File

@@ -20,26 +20,6 @@ namespace boost { namespace python
namespace boost { namespace python { namespace detail {
// for "readable" error messages
template <class T> struct must_use_a_result_handler_to_wrap_functions_returning
# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
{}
# endif
;
struct to_python_generator
{
template <class R>
struct apply
{
typedef typename mpl::select_type<
is_reference<R>::value | is_pointer<R>::value
, must_use_a_result_handler_to_wrap_functions_returning<R>
, to_python<R>
>::type type;
};
};
struct caller
{
typedef PyObject* result_type;

View File

@@ -0,0 +1,99 @@
// 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 MSVC_TYPEINFO_DWA200222_HPP
# define MSVC_TYPEINFO_DWA200222_HPP
#include <boost/type.hpp>
#include <typeinfo>
//
// Fix for MSVC's broken typeid() implementation which doesn't strip
// decoration. This fix doesn't handle cv-qualified array types. It
// could probably be done, but I haven't figured it out yet.
//
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(BOOST_INTEL_CXX_VERSION) && BOOST_INTEL_CXX_VERSION <= 600
namespace boost { namespace python { namespace detail {
typedef std::type_info const& typeinfo;
template<int>struct value_id_accessor;
template<>
struct value_id_accessor<0>
{
template <class T>
static typeinfo get(T*) { return typeid(T); }
};
template<>
struct value_id_accessor<1>
{
template <class T>
static typeinfo get(T const*) { return typeid(T); }
};
template<>
struct value_id_accessor<2>
{
template <class T>
static typeinfo get(T volatile*) { return typeid(T); }
};
template<>
struct value_id_accessor<3>
{
template <class T>
static typeinfo get(T const volatile*) { return typeid(T); }
};
template <bool> struct bool_t{};
template <class T>
inline typeinfo typeid_nonref(boost::type<T>* = 0)
{
BOOST_STATIC_CONSTANT(bool, c = is_const<T>::value);
BOOST_STATIC_CONSTANT(bool, v = is_volatile<T>::value);
return value_id_accessor<(2 * v + c)>::get((T*)0);
}
template <class T>
inline typeinfo typeid_ref(boost::type<T>*, ...)
{
return typeid_nonref<T>();
}
template <class U, class T>
inline typeinfo typeid_ref(boost::type<U>*, T& (*)())
{
return typeid_nonref<T>();
}
template <class T>
inline typeinfo typeid_array(bool_t<false>, boost::type<T>* = 0)
{
typedef T (*x)();
return typeid_ref((boost::type<T>*)0, x(0));
}
template <class T>
inline typeinfo typeid_array(bool_t<true>, boost::type<T>* = 0)
{
return typeid_nonref<T>();
}
template <class T>
inline typeinfo msvc_typeid(boost::type<T>* = 0)
{
typedef bool_t<is_array<T>::value> tag;
return typeid_array(tag(), (boost::type<T>*)0);
}
}}} // namespace boost::python::detail
# endif // BOOST_MSVC
#endif // MSVC_TYPEINFO_DWA200222_HPP

View File

@@ -11,17 +11,10 @@
#ifndef RETURNING_DWA20011201_HPP
# define RETURNING_DWA20011201_HPP
//# include <boost/python/detail/config.hpp>
# include <boost/python/detail/wrap_python.hpp>
# include <boost/config.hpp>
# include <boost/python/detail/none.hpp>
# include <boost/python/from_python.hpp>
# include <boost/python/to_python.hpp>
namespace boost { namespace python
{
template <class T> struct to_python;
}} // namespace boost::python
namespace boost { namespace python { namespace detail {

View File

@@ -8,7 +8,6 @@
# include <boost/python/object/function.hpp>
# include <boost/python/object/make_holder.hpp>
# include <boost/python/converter/registration.hpp>
# include <boost/python/detail/caller.hpp>
# include <boost/python/detail/arg_tuple_size.hpp>
# include <boost/mpl/size.hpp>

View File

@@ -6,21 +6,18 @@
#ifndef CLASS_WRAPPER_DWA20011221_HPP
# define CLASS_WRAPPER_DWA20011221_HPP
# include <boost/python/object/class.hpp>
# include <boost/python/object/value_holder.hpp>
# include <boost/python/reference.hpp>
# include <boost/python/converter/to_python.hpp>
# include <memory>
# include <boost/python/to_python_converter.hpp>
namespace boost { namespace python { namespace objects {
template <class T>
struct class_wrapper
: converter::to_python_converter<T const&>
: to_python_converter<T, class_wrapper<T> >
{
class_wrapper(ref const& type_)
: converter::to_python_converter<T const&>(convert)
, m_class_object_keeper(type_)
: m_class_object_keeper(type_)
{
assert(type_->ob_type == (PyTypeObject*)class_metatype().get());
m_class_object = (PyTypeObject*)type_.get();
@@ -31,9 +28,8 @@ struct class_wrapper
// Don't call the type to do the construction, since that
// would require the registration of an __init__ copy
// constructor. Instead, just construct the object in place.
PyObject* raw_result = (PyObject*)PyObject_New(
instance, m_class_object);
PyObject* raw_result = m_class_object->tp_alloc(m_class_object, 0);
if (raw_result == 0)
return 0;
@@ -41,6 +37,8 @@ struct class_wrapper
// exceptions.
ref result(raw_result, ref::allow_null());
((instance*)raw_result)->objects = 0;
// Build a value_holder to contain the object using the copy
// constructor
value_holder<T>* p = new value_holder<T>(raw_result, cref(x));

View File

@@ -1,37 +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 TO_PYTHON_DWA2002128_HPP
# define TO_PYTHON_DWA2002128_HPP
# include <boost/python/converter/to_python.hpp>
# include <boost/python/converter/source.hpp>
namespace boost { namespace python {
template <class T>
struct to_python
: converter::to_python_lookup<typename converter::source<T>::type>
{
};
// specialization for PyObject*
template <>
struct to_python<PyObject*>
{
bool convertible() const { return true; }
PyObject* operator()(PyObject* source) const { return source; }
};
template <>
struct to_python<PyObject*const&>
{
bool convertible() const { return true; }
PyObject* operator()(PyObject* source) const { return source; }
};
}} // namespace boost::python
#endif // TO_PYTHON_DWA2002128_HPP

View File

@@ -200,7 +200,6 @@ namespace
#define REGISTER_INT_CONVERTERS(U) register_int_converters<U>()
#define REGISTER_INT_CONVERTERS2(U) REGISTER_INT_CONVERTERS(signed U); REGISTER_INT_CONVERTERS(unsigned U)
void initialize_builtin_converters()
{
REGISTER_INT_CONVERTERS2(char);

View File

@@ -5,6 +5,7 @@
// to its suitability for any purpose.
#include <boost/python/converter/from_python.hpp>
#include <boost/python/converter/registry.hpp>
namespace boost { namespace python { namespace converter {
@@ -14,14 +15,12 @@ from_python_converter_base::from_python_converter_base(
)
: body(type)
, m_convertible(checker)
{
registry::insert(*this);
}
from_python_converter_base::~from_python_converter_base()
{
if (can_unregister())
registry::remove(*this);
// Insert this in the converter chain.
from_python_converter_base*& head = registry::from_python_chain(type);
m_next = head;
head = this;
}
}}} // namespace boost::python::converter

View File

@@ -3,23 +3,32 @@
// 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/from_python.hpp>
# include <boost/python/converter/builtin_converters.hpp>
# include <boost/detail/binary_search.hpp>
# include <map>
# include <algorithm>
# include <stdexcept>
# ifdef BOOST_PYTHON_TRACE
# include <iostream>
# endif
#include <boost/python/converter/registry.hpp>
#include <boost/python/converter/builtin_converters.hpp>
#include <map>
#include <stdexcept>
namespace boost { namespace python { namespace converter {
namespace // <unnamed>
{
typedef std::map<type_id_t, registry::entry> registry_t;
// These are the elements stored in the registry
struct entry
{
entry();
// 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;
// The class object associated with this type
PyTypeObject* m_class_object;
};
typedef std::map<type_id_t, entry> registry_t;
registry_t& entries()
{
@@ -35,10 +44,7 @@ namespace // <unnamed>
}
return registry;
}
} // namespace <unnamed>
namespace registry
{
entry* find(type_id_t type)
{
return &entries()[type];
@@ -46,128 +52,40 @@ namespace registry
entry::entry()
: m_to_python_converter(0)
, m_from_python_converters(0)
, m_class_object(0)
{
}
} // namespace <unnamed>
entry::~entry()
namespace registry
{
to_python_value_function const& to_python_function(
undecorated_type_id_t key)
{
if (m_to_python_converter != 0)
m_to_python_converter->m_can_unregister = false;
for (from_python_converters::iterator p = m_from_python_converters.begin()
; p != m_from_python_converters.end()
; ++p)
{
(*p)->m_can_unregister = false;
}
}
from_python_converter_base const*
entry::get_from_python(PyObject* p, void*& data_out) const
{
for (from_python_converters::const_iterator q = m_from_python_converters.begin(),
finish = m_from_python_converters.end();
q != finish;
++q)
{
void* const data = (*q)->convertible(p);
if (data != 0)
{
data_out = data;
return *q;
break;
}
}
return 0;
return find(key)->m_to_python_converter;
}
to_python_function_base entry::get_to_python() const
void insert(to_python_value_function f, undecorated_type_id_t source_t)
{
return m_to_python_converter
? m_to_python_converter->converter()
: 0;
}
entry::from_python_converters::iterator entry::find(from_python_converter_base const& x)
{
return std::find(m_from_python_converters.begin(), m_from_python_converters.end(), &x);
}
void entry::insert(from_python_converter_base& x)
{
from_python_converters::iterator p = this->find(x);
if (p != m_from_python_converters.end())
{
assert(!"converter already registered");
throw std::runtime_error(
"trying to register unrapper which is already registered");
}
m_from_python_converters.push_back(&x);
}
void entry::remove(from_python_converter_base& x)
{
from_python_converters::iterator p = find(x);
// Be sure we're not removing a converter which hasn't been
// registered.
if (p == m_from_python_converters.end())
{
assert(!"trying to unregister from_python_converter which is not registered");
throw std::runtime_error(
"trying to unregister from_python_converter which is not registered");
}
m_from_python_converters.erase(p);
}
void entry::insert(to_python_converter_base& x)
{
assert(m_to_python_converter == 0); // we have a problem otherwise
if (m_to_python_converter != 0)
to_python_value_function& slot = find(source_t)->m_to_python_converter;
assert(slot == 0); // we have a problem otherwise
if (slot != 0)
{
throw std::runtime_error(
"trying to register to_python_converter for a type which already has a registered to_python_converter");
}
m_to_python_converter = &x;
slot = f;
}
from_python_converter_base*& from_python_chain(type_id_t key)
{
return find(key)->m_from_python_converters;
}
void entry::remove(to_python_converter_base& x)
PyTypeObject*& class_object(undecorated_type_id_t key)
{
assert(m_to_python_converter == &x);
if (m_to_python_converter != &x)
{
throw std::runtime_error(
"trying to unregister a to_python_converter which is not registered");
}
m_to_python_converter = 0;
}
void insert(to_python_converter_base& w)
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "inserting to_python_converter for " << w.key() << std::endl;
# endif
find(w.key())->insert(w);
}
void insert(from_python_converter_base& u)
{
# ifdef BOOST_PYTHON_TRACE
std::cout << "inserting from_python_converter for " << u.key() << std::endl;
# endif
find(u.key())->insert(u);
}
void remove(to_python_converter_base& w)
{
find(w.key())->remove(w);
}
void remove(from_python_converter_base& u)
{
find(u.key())->remove(u);
return find(key)->m_class_object;
}
} // namespace registry

View File

@@ -1,24 +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.
#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

@@ -21,18 +21,12 @@ BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, undecorated_type_id
BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, type_id_t const& x)
{
os << x.m_base_type;
// VC6 mistakenly distinguishes typeid(X) from typeid(X const)
// from typeid(X&)... so the name is already correct. I have it
// from Jason Shirk that VC7.0 has the same bug but it will be
// fixed in 7.1
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
if (x.m_decoration & type_id_t::const_)
os << " const";
if (x.m_decoration & type_id_t::volatile_)
os << " volatile";
if (x.m_decoration & type_id_t::reference)
os << "&";
# endif
return os;
}

View File

@@ -6,7 +6,6 @@
#include <boost/python/detail/config.hpp>
#include <boost/python/detail/wrap_python.hpp>
#include <boost/python/object/class.hpp>
#include <boost/python/object/class_wrapper.hpp>
#include <boost/python/objects.hpp>
#include <boost/python/detail/map_entry.hpp>
#include <boost/detail/binary_search.hpp>
@@ -122,7 +121,7 @@ PyTypeObject class_type_object = {
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew
};

View File

@@ -16,6 +16,7 @@
#include <boost/python/return_value_policy.hpp>
#include <boost/python/converter/class.hpp>
#include <boost/python/reference_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>
@@ -105,26 +106,19 @@ PyObject* new_simple()
// are selected.
//
using boost::python::converter::from_python_data;
using boost::python::to_python_converter;
// Wrap a simple by converting it to a Simple
PyObject* simple_to_python(simple const& x)
// Wrap a simple by copying it into a Simple
struct simple_to_python
: to_python_converter<simple, simple_to_python>
{
SimpleObject* p = PyObject_New(SimpleObject, &SimpleType);
p->x = x;
return (PyObject*)p;
}
// wrap a mutable reference to a simple by converting it to a
// Simple. Normally we wouldn't do it this way, since modifications to
// the result clearly don't change the original object, but here we're
// just proving that the mechanism works.
PyObject* simple_ref_to_python(simple& x)
{
SimpleObject* p = PyObject_New(SimpleObject, &SimpleType);
p->x = x;
return (PyObject*)p;
}
static PyObject* convert(simple const& x)
{
SimpleObject* p = PyObject_New(SimpleObject, &SimpleType);
p->x = x;
return (PyObject*)p;
}
};
int noddy_to_int(PyObject* p, from_python_data&)
{
@@ -184,16 +178,15 @@ struct D : B, C
int x;
};
int take_a(A const& a) { return a.x; }
int take_b(B const& b) { return b.x; }
int take_c(C const& c) { return c.x; }
int take_d(D const& d) { return d.x; }
A take_a(A const& a) { return a; }
B take_b(B const& b) { return b; }
C take_c(C const& c) { return c; }
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::to_python_converter;
using boost::python::converter::from_python_converter;
using boost::python::reference_from_python;
using boost::python::value_from_python;
@@ -204,7 +197,7 @@ BOOST_PYTHON_MODULE_INIT(m1)
using boost::mpl::type_list;
// Create the converters; they are self-registering/unregistering.
static to_python_converter<simple const&> c1(simple_to_python);
static simple_to_python c1;
static from_python_converter<int> c2(
&(boost::python::type_from_python<&NoddyType>::convertible), noddy_to_int);
@@ -219,10 +212,7 @@ BOOST_PYTHON_MODULE_INIT(m1)
, 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

@@ -73,8 +73,8 @@ are a complicated constructor and member function, respectively.
>>> d = D()
------
>>> take_a(a)
0
>>> take_a(a).name()
'A'
>>> try:
... take_b(a)
@@ -92,11 +92,11 @@ are a complicated constructor and member function, respectively.
... else: print 'no exception'
------
>>> take_a(b)
0
>>> take_a(b).name()
'A'
>>> take_b(b)
1
>>> take_b(b).name()
'B'
>>> try:
... take_c(b)
@@ -109,16 +109,16 @@ are a complicated constructor and member function, respectively.
... else: print 'no exception'
-------
>>> take_a(c)
0
>>> take_a(c).name()
'A'
>>> try:
... take_b(c)
... except: pass
... else: print 'no exception'
>>> take_c(c)
2
>>> take_c(c).name()
'C'
>>> try:
... take_d(c)
@@ -126,14 +126,14 @@ are a complicated constructor and member function, respectively.
... else: print 'no exception'
-------
>>> take_a(d)
0
>>> take_b(d)
1
>>> take_c(d)
2
>>> take_d(d)
3
>>> take_a(d).name()
'A'
>>> take_b(d).name()
'B'
>>> take_c(d).name()
'C'
>>> take_d(d).name()
'D'
"""