2
0
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:
Dave Abrahams
2002-12-14 00:10:52 +00:00
parent 4a5817d8ba
commit abd22f1273
3 changed files with 61 additions and 19 deletions

View File

@@ -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))

View File

@@ -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()
{

View File

@@ -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)