mirror of
https://github.com/boostorg/python.git
synced 2026-01-24 18:12:43 +00:00
Handle unsigned long values that don't fit in a long.
[SVN r16606]
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <string>
|
||||
# include <complex>
|
||||
# include <limits>
|
||||
|
||||
// Since all we can use to decide how to convert an object to_python
|
||||
// is its C++ type, there can be only one such converter for each
|
||||
@@ -80,9 +81,12 @@ namespace detail
|
||||
BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T,expr)
|
||||
|
||||
// Specialize converters for signed and unsigned T to Python Int
|
||||
# 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))
|
||||
# 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, static_cast<unsigned long>(x) > std::numeric_limits<long>::max() \
|
||||
? PyLong_FromUnsignedLong(x) \
|
||||
: PyInt_FromLong(x))
|
||||
|
||||
// Bool is not signed.
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, PyInt_FromLong(x))
|
||||
|
||||
@@ -65,8 +65,8 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
// A SlotPolicy for extracting integer types from Python objects
|
||||
struct int_rvalue_from_python_base
|
||||
// A SlotPolicy for extracting signed integer types from Python objects
|
||||
struct signed_int_rvalue_from_python_base
|
||||
{
|
||||
static unaryfunc* get_slot(PyObject* obj)
|
||||
{
|
||||
@@ -80,7 +80,7 @@ namespace
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct int_rvalue_from_python : int_rvalue_from_python_base
|
||||
struct signed_int_rvalue_from_python : signed_int_rvalue_from_python_base
|
||||
{
|
||||
static T extract(PyObject* intermediate)
|
||||
{
|
||||
@@ -88,6 +88,41 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
// identity_unaryfunc/py_object_identity -- manufacture a unaryfunc
|
||||
// "slot" which just returns its argument.
|
||||
extern "C" PyObject* identity_unaryfunc(PyObject* x)
|
||||
{
|
||||
Py_INCREF(x);
|
||||
return x;
|
||||
}
|
||||
unaryfunc py_object_identity = identity_unaryfunc;
|
||||
|
||||
// A SlotPolicy for extracting unsigned integer types from Python objects
|
||||
struct unsigned_int_rvalue_from_python_base
|
||||
{
|
||||
static unaryfunc* get_slot(PyObject* obj)
|
||||
{
|
||||
PyNumberMethods* number_methods = obj->ob_type->tp_as_number;
|
||||
if (number_methods == 0)
|
||||
return 0;
|
||||
|
||||
return (PyInt_Check(obj) || PyLong_Check(obj))
|
||||
? &py_object_identity : 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct unsigned_int_rvalue_from_python : unsigned_int_rvalue_from_python_base
|
||||
{
|
||||
static T extract(PyObject* intermediate)
|
||||
{
|
||||
return numeric_cast<T>(
|
||||
PyLong_Check(intermediate)
|
||||
? PyLong_AsUnsignedLong(intermediate)
|
||||
: PyInt_AS_LONG(intermediate));
|
||||
}
|
||||
};
|
||||
|
||||
// Checking Python's macro instead of Boost's - we don't seem to get
|
||||
// the config right all the time. Furthermore, Python's is defined
|
||||
// when long long is absent but __int64 is present.
|
||||
@@ -155,17 +190,6 @@ namespace
|
||||
};
|
||||
#endif
|
||||
|
||||
// identity_unaryfunc/py_object_identity -- manufacture a unaryfunc
|
||||
// "slot" which just returns its argument. Used for bool
|
||||
// conversions, since all Python objects are directly convertible to
|
||||
// bool
|
||||
extern "C" PyObject* identity_unaryfunc(PyObject* x)
|
||||
{
|
||||
Py_INCREF(x);
|
||||
return x;
|
||||
}
|
||||
unaryfunc py_object_identity = identity_unaryfunc;
|
||||
|
||||
// A SlotPolicy for extracting bool from a Python object
|
||||
struct bool_rvalue_from_python
|
||||
{
|
||||
@@ -282,8 +306,15 @@ BOOST_PYTHON_DECL PyObject* do_arg_to_python(PyObject* x)
|
||||
return x;
|
||||
}
|
||||
|
||||
#define REGISTER_INT_CONVERTERS(U) slot_rvalue_from_python<U,int_rvalue_from_python<U> >()
|
||||
#define REGISTER_INT_CONVERTERS2(U) REGISTER_INT_CONVERTERS(signed U); REGISTER_INT_CONVERTERS(unsigned U)
|
||||
#define REGISTER_INT_CONVERTERS(signedness, U) \
|
||||
slot_rvalue_from_python< \
|
||||
signedness U \
|
||||
,signedness##_int_rvalue_from_python<signedness U> \
|
||||
>()
|
||||
|
||||
#define REGISTER_INT_CONVERTERS2(U) \
|
||||
REGISTER_INT_CONVERTERS(signed, U); \
|
||||
REGISTER_INT_CONVERTERS(unsigned, U)
|
||||
|
||||
void initialize_builtin_converters()
|
||||
{
|
||||
|
||||
@@ -38,6 +38,13 @@ r"""
|
||||
42
|
||||
>>> rewrap_value_unsigned_long(42)
|
||||
42
|
||||
|
||||
test unsigned long values which don't fit in a signed long.
|
||||
strip any 'L' characters in case the platform has > 32 bit longs
|
||||
|
||||
>>> hex(rewrap_value_unsigned_long(0x80000001L)).replace('L','')
|
||||
'0x80000001'
|
||||
|
||||
>>> rewrap_value_long_long(42)
|
||||
42L
|
||||
>>> rewrap_value_unsigned_long_long(42)
|
||||
|
||||
Reference in New Issue
Block a user