2
0
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:
Dave Abrahams
2002-01-31 05:53:54 +00:00
parent 88a8721b89
commit 6a75fa83b5
26 changed files with 1259 additions and 661 deletions

View File

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

View File

@@ -0,0 +1,27 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/from_python.hpp>
namespace boost { namespace python { namespace converter {
from_python_converter_base::from_python_converter_base(
type_id_t type
, from_python_check checker
)
: body(type)
, m_convertible(checker)
{
registry::insert(*this);
}
from_python_converter_base::~from_python_converter_base()
{
if (can_unregister())
registry::remove(*this);
}
}}} // namespace boost::python::converter

View File

@@ -0,0 +1,24 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/converter/to_python.hpp>
#include <boost/python/converter/registry.hpp>
namespace boost { namespace python { namespace converter {
to_python_converter_base::to_python_converter_base(type_id_t key, to_python_function_base convert)
: body(key)
, m_convert(convert)
{
registry::insert(*this);
}
to_python_converter_base::~to_python_converter_base()
{
registry::remove(*this);
}
}}} // namespace boost::python::converter