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:
1
Jamfile
1
Jamfile
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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>()
|
||||
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
99
include/boost/python/detail/msvc_typeinfo.hpp
Normal file
99
include/boost/python/detail/msvc_typeinfo.hpp
Normal 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
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
44
test/m1.cpp
44
test/m1.cpp
@@ -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<
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user