mirror of
https://github.com/boostorg/python.git
synced 2026-01-24 06:02:14 +00:00
New conversion methods, builtin converters
---------------------------------------------------------------------- Committing in . Modified Files: boost/python/reference_from_python.hpp boost/python/value_from_python.hpp boost/python/converter/body.hpp boost/python/converter/handle.hpp libs/python/src/converter/builtin_converters.cpp libs/python/test/m1.cpp libs/python/test/m2.cpp Added Files: boost/python/converter/builtin_converters.hpp boost/python/converter/builtin_to_python_converters.hpp boost/python/converter/from_python.hpp boost/python/converter/from_python_data.hpp boost/python/converter/from_python_function.hpp boost/python/converter/to_python.hpp boost/python/converter/to_python_function.hpp boost/python/object/auto_ptr_generator.hpp boost/python/object/pointer_holder.hpp libs/python/src/converter/from_python.cpp libs/python/src/converter/to_python.cpp libs/python/test/test_builtin_converters.cpp libs/python/test/test_builtin_converters.py Removed Files: boost/python/convert.hpp boost/python/converter/unwrap.hpp boost/python/converter/unwrapper.hpp boost/python/converter/wrap.hpp boost/python/converter/wrapper.hpp boost/python/object/class_unwrapper.hpp ---------------------------------------------------------------------- [SVN r12596]
This commit is contained in:
@@ -8,7 +8,8 @@
|
||||
#include <boost/python/detail/wrap_python.hpp>
|
||||
#include <boost/python/converter/builtin_converters.hpp>
|
||||
#include <boost/python/converter/target.hpp>
|
||||
#include <boost/python/converter/from_python.hpp>
|
||||
#include <boost/python/value_from_python.hpp>
|
||||
#include <boost/python/converter/from_python_data.hpp>
|
||||
#include <boost/python/reference.hpp>
|
||||
#include <boost/cast.hpp>
|
||||
//#include <boost/mpl/type_list.hpp>
|
||||
@@ -18,113 +19,185 @@ namespace boost { namespace python { namespace converter {
|
||||
|
||||
namespace
|
||||
{
|
||||
struct int_value_functions_base
|
||||
// Only an object which we know is holding a char const* can be
|
||||
// converted to one
|
||||
struct convertible_to_cstring
|
||||
{
|
||||
static void* convertible(PyObject* obj)
|
||||
static unaryfunc* execute(PyObject* obj)
|
||||
{
|
||||
PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
|
||||
|
||||
return number_methods && number_methods->nb_int
|
||||
? &number_methods->nb_int : 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct int_value_functions : int_value_functions_base
|
||||
{
|
||||
static T convert(PyObject* obj, from_python_data& data)
|
||||
{
|
||||
unaryfunc f = *static_cast<unaryfunc*>(data.stage1);
|
||||
ref int_object(f(obj));
|
||||
return numeric_cast<T>(PyInt_AsLong(int_object.get()));
|
||||
return PyString_Check(obj) ? &obj->ob_type->tp_str : 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct cstring_value_functions
|
||||
struct extract_cstring
|
||||
{
|
||||
static void* convertible(PyObject* obj)
|
||||
{
|
||||
return PyString_Check(obj) ? obj : 0;
|
||||
}
|
||||
|
||||
static char const* convert(PyObject* obj, from_python_data&)
|
||||
static char const* execute(PyObject* obj)
|
||||
{
|
||||
return PyString_AsString(obj);
|
||||
}
|
||||
};
|
||||
|
||||
char constructed;
|
||||
|
||||
struct string_cref_functions
|
||||
// Any object which can be converted to a Python string can also be
|
||||
// converted to a C++ string, since the latter owns its bytes.
|
||||
struct convertible_to_string
|
||||
{
|
||||
typedef std::string const& result_type;
|
||||
|
||||
static void* convertible(PyObject* obj)
|
||||
static unaryfunc* execute(PyObject* obj)
|
||||
{
|
||||
return obj->ob_type->tp_str ? &obj->ob_type->tp_str : 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Transform a function returning a unaryfunc* into one that returns a void*
|
||||
template <class F>
|
||||
struct return_void_ptr
|
||||
{
|
||||
static void* execute(PyObject* p) { return F::execute(p); }
|
||||
};
|
||||
|
||||
template <
|
||||
class T // The target type
|
||||
, class Convertible // returns a pointer to a unaryfunc producing an object
|
||||
, class TExtract // ...from which TExtract extracts T's constructor argument
|
||||
>
|
||||
struct tp_scalar_from_python
|
||||
: from_python_converter<T>
|
||||
{
|
||||
private:
|
||||
typedef return_void_ptr<Convertible> convertible_fn;
|
||||
|
||||
static std::string const& convert(
|
||||
PyObject* obj, from_python_data& data)
|
||||
public:
|
||||
tp_scalar_from_python()
|
||||
: from_python_converter<T>(
|
||||
&convertible_fn::execute
|
||||
, convert)
|
||||
{}
|
||||
|
||||
static T convert(PyObject* obj, from_python_data& data)
|
||||
{
|
||||
ref string_object((**static_cast<reprfunc*>(data.stage1))(obj));
|
||||
void* storage = get_storage<result_type>(data);
|
||||
std::string* p = new (storage) std::string(PyString_AsString(string_object.get()));
|
||||
unaryfunc converter = *(unaryfunc*)data.stage1;
|
||||
ref converted(converter(obj));
|
||||
return TExtract::execute(converted.get());
|
||||
}
|
||||
};
|
||||
|
||||
// Extract a reference to T using the functions in the source
|
||||
// object's type slots
|
||||
template <
|
||||
class T // The target type
|
||||
, class Convertible // returns a pointer to a unaryfunc producing an object
|
||||
, class TExtract // ...from which TExtract extracts T's constructor argument
|
||||
>
|
||||
struct tp_cref_from_python
|
||||
: value_from_python<T, tp_cref_from_python<T,Convertible,TExtract> >
|
||||
{
|
||||
private:
|
||||
typedef value_from_python<T, tp_cref_from_python<T,Convertible,TExtract> > base;
|
||||
|
||||
public:
|
||||
tp_cref_from_python()
|
||||
: base(&return_void_ptr<Convertible>::execute)
|
||||
{}
|
||||
|
||||
static T const& convert(PyObject* obj, from_python_data& data)
|
||||
{
|
||||
unaryfunc converter = *(unaryfunc*)data.stage1;
|
||||
|
||||
void* storage = get_storage(data);
|
||||
|
||||
ref converted(converter(obj));
|
||||
|
||||
T* const p = new (storage) T(TExtract::execute(converted.get()));
|
||||
|
||||
// note that construction is successful.
|
||||
data.stage1 = &constructed;
|
||||
data.stage1 = p;
|
||||
|
||||
return *p;
|
||||
}
|
||||
};
|
||||
|
||||
static void destroy(from_python_data& data)
|
||||
struct convertible_to_int
|
||||
{
|
||||
static unaryfunc* execute(PyObject* obj)
|
||||
{
|
||||
if (data.stage1 == &constructed)
|
||||
PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
|
||||
if (number_methods == 0)
|
||||
return 0;
|
||||
|
||||
// For floating types, return the float conversion slot to avoid
|
||||
// creating a new object. We'll handle that in
|
||||
// py_int_or_float_as_long, below
|
||||
if (PyObject_TypeCheck(obj, &PyFloat_Type) && number_methods->nb_float)
|
||||
return &number_methods->nb_float;
|
||||
|
||||
return number_methods && number_methods->nb_int
|
||||
? &number_methods->nb_int : 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct py_int_or_float_as_long
|
||||
{
|
||||
static long execute(PyObject* obj)
|
||||
{
|
||||
if (PyObject_TypeCheck(obj, &PyFloat_Type))
|
||||
{
|
||||
typedef std::string string_t;
|
||||
void* storage = get_storage<result_type>(data);
|
||||
((string_t*)storage)->~string_t();
|
||||
return numeric_cast<long>(PyFloat_AS_DOUBLE(obj));
|
||||
}
|
||||
else
|
||||
{
|
||||
return PyInt_AS_LONG(obj);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Base>
|
||||
struct rvalue_const_ref_functions : Base
|
||||
struct convertible_to_double
|
||||
{
|
||||
static T const& convert(PyObject* obj, from_python_data& data)
|
||||
static unaryfunc* execute(PyObject* obj)
|
||||
{
|
||||
void* storage = get_storage<T const&>(data);
|
||||
T* p = new (storage) T(Base::convert(obj,data));
|
||||
|
||||
// note that construction is successful.
|
||||
data.stage1 = &constructed;
|
||||
return *p;
|
||||
PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
|
||||
if (number_methods == 0)
|
||||
return 0;
|
||||
|
||||
// For integer types, return the tp_int conversion slot to avoid
|
||||
// creating a new object. We'll handle that in
|
||||
// py_float_or_int_as_double, below
|
||||
if (PyObject_TypeCheck(obj, &PyInt_Type) && number_methods->nb_int)
|
||||
return &number_methods->nb_int;
|
||||
|
||||
return number_methods && number_methods->nb_float
|
||||
? &number_methods->nb_float : 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct register_int_converters
|
||||
struct py_float_or_int_as_double
|
||||
{
|
||||
template <class Ignored, class T>
|
||||
struct apply
|
||||
static double execute(PyObject* obj)
|
||||
{
|
||||
typedef void type;
|
||||
|
||||
static void execute()
|
||||
if (PyObject_TypeCheck(obj, &PyInt_Type))
|
||||
{
|
||||
typedef int_value_functions<T> value_functions;
|
||||
typedef rvalue_const_ref_functions<T,value_functions> cref_functions;
|
||||
|
||||
static from_python_converter<T> value_from_python(
|
||||
value_functions::convertible
|
||||
, value_functions::convert);
|
||||
static from_python_converter<T const&> cref_from_python(
|
||||
cref_functions::convertible
|
||||
, cref_functions::convert);
|
||||
};
|
||||
};
|
||||
return PyInt_AS_LONG(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
return PyFloat_AS_DOUBLE(obj);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#define REGISTER_INT_CONVERTERS(U) register_int_converters::apply<void,U>::execute()
|
||||
template <class T, class Convertible, class Convert>
|
||||
struct scalar_from_python
|
||||
{
|
||||
tp_cref_from_python<T,Convertible,Convert> cref_converter;
|
||||
tp_scalar_from_python<T,Convertible,Convert> value_converter;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void register_int_converters(T* = 0)
|
||||
{
|
||||
static scalar_from_python<T, convertible_to_int, py_int_or_float_as_long> x;
|
||||
};
|
||||
}
|
||||
|
||||
#define REGISTER_INT_CONVERTERS(U) register_int_converters<U>()
|
||||
#define REGISTER_INT_CONVERTERS2(U) REGISTER_INT_CONVERTERS(signed U); REGISTER_INT_CONVERTERS(unsigned U)
|
||||
|
||||
|
||||
@@ -134,20 +207,21 @@ void initialize_builtin_converters()
|
||||
REGISTER_INT_CONVERTERS2(short);
|
||||
REGISTER_INT_CONVERTERS2(int);
|
||||
REGISTER_INT_CONVERTERS2(long);
|
||||
// mpl::for_each<integral_types,void,register_int_converters>::execute();
|
||||
|
||||
static from_python_converter<char const*> cstring_from_python(
|
||||
&cstring_value_functions::convertible
|
||||
, &cstring_value_functions::convert);
|
||||
static scalar_from_python<
|
||||
float,convertible_to_double,py_float_or_int_as_double> float_from_python;
|
||||
|
||||
static scalar_from_python<
|
||||
double,convertible_to_double,py_float_or_int_as_double> double_from_python;
|
||||
|
||||
static scalar_from_python<
|
||||
long double,convertible_to_double,py_float_or_int_as_double> long_double_from_python;
|
||||
|
||||
static scalar_from_python<
|
||||
char const*, convertible_to_cstring, extract_cstring> cstring_from_python;
|
||||
|
||||
static from_python_converter<char const*const&> cstring_cref_from_python(
|
||||
&rvalue_const_ref_functions<char const*,cstring_value_functions>::convertible
|
||||
, &rvalue_const_ref_functions<char const*, cstring_value_functions>::convert);
|
||||
|
||||
static from_python_converter<std::string const&> string_cref_from_python(
|
||||
&string_cref_functions::convertible
|
||||
, &string_cref_functions::convert
|
||||
, &string_cref_functions::destroy);
|
||||
static tp_cref_from_python<
|
||||
std::string, convertible_to_string, extract_cstring> string_from_python;
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
27
src/converter/from_python.cpp
Normal file
27
src/converter/from_python.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include <boost/python/converter/from_python.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
from_python_converter_base::from_python_converter_base(
|
||||
type_id_t type
|
||||
, from_python_check checker
|
||||
)
|
||||
: body(type)
|
||||
, m_convertible(checker)
|
||||
{
|
||||
registry::insert(*this);
|
||||
}
|
||||
|
||||
from_python_converter_base::~from_python_converter_base()
|
||||
{
|
||||
if (can_unregister())
|
||||
registry::remove(*this);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
24
src/converter/to_python.cpp
Normal file
24
src/converter/to_python.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include <boost/python/converter/to_python.hpp>
|
||||
#include <boost/python/converter/registry.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
to_python_converter_base::to_python_converter_base(type_id_t key, to_python_function_base convert)
|
||||
: body(key)
|
||||
, m_convert(convert)
|
||||
{
|
||||
registry::insert(*this);
|
||||
}
|
||||
|
||||
to_python_converter_base::~to_python_converter_base()
|
||||
{
|
||||
registry::remove(*this);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
Reference in New Issue
Block a user