generic integer type handling

This commit is contained in:
Wenzel Jakob 2015-11-30 12:30:28 +01:00
parent 7f8d1c20f1
commit 60c36db1c9
4 changed files with 161 additions and 127 deletions

View File

@ -1,13 +1,3 @@
Help on built-in function kw_func
kkww__ffuunncc(...)
Signature : (x : int32_t, y : int32_t) -> None
Help on built-in function kw_func2
kkww__ffuunncc22(...)
Signature : (x : int32_t = 100, y : int32_t = 200) -> None
kw_func(x=5, y=10) kw_func(x=5, y=10)
kw_func(x=5, y=10) kw_func(x=5, y=10)
kw_func(x=5, y=10) kw_func(x=5, y=10)
@ -17,3 +7,13 @@ kw_func(x=5, y=200)
kw_func(x=100, y=10) kw_func(x=100, y=10)
kw_func(x=5, y=10) kw_func(x=5, y=10)
kw_func(x=5, y=10) kw_func(x=5, y=10)
Help on built-in function kw_func
kkww__ffuunncc(...) method of builtins.PyCapsule instance
Signature : (x : int, y : int) -> None
Help on built-in function kw_func2
kkww__ffuunncc22(...) method of builtins.PyCapsule instance
Signature : (x : int = 100, y : int = 200) -> None

View File

@ -1,14 +1,10 @@
15
5
Example2: No constructor defined!
can't set attribute
key: key2, value=value2
key: key, value=value key: key, value=value
key: key2, value=value2
key: key, value=value key: key, value=value
key: key2, value=value2 key: key2, value=value2
key: key3 key: key3
key: key2
key: key1 key: key1
key: key2
key: key1 key: key1
key: key2 key: key2
key: key3 key: key3
@ -17,105 +13,107 @@ list item 0: overwritten
list item 1: value2 list item 1: value2
list item 0: value list item 0: value
list item 1: value2 list item 1: value2
15
5
example.Example2: No constructor defined!
can't set attribute
This exception was intentionally thrown. This exception was intentionally thrown.
(u'test', True) ('test', True)
(5L, u'test', True) (5, 'test', True)
Help on class Example2 in module example Help on class Example2 in module example
class EExxaammppllee22(__builtin__.object) class EExxaammppllee22(builtins.object)
| Example 2 documentation | Example 2 documentation
| |
| Methods defined here: | Methods defined here:
| |
| ____iinniitt____(...) | ____iinniitt____(self, /, *args, **kwargs)
| x.__init__(...) initializes x; see help(type(x)) for signature | Initialize self. See help(type(self)) for accurate signature.
| |
| ggeett__ddiicctt(...) | ____nneeww____ = <built-in method __new__ of example.Example2_meta object>
| Signature : (Example2) -> dict | ggeett__ddiicctt(...) from builtins.PyCapsule
| Signature : (example.Example2) -> dict
| |
| Return a Python dictionary | Return a Python dictionary
| |
| ggeett__ddiicctt__22(...) | ggeett__ddiicctt__22(...) from builtins.PyCapsule
| Signature : (Example2) -> dict<str, str> | Signature : (example.Example2) -> dict<str, str>
| |
| Return a C++ dictionary | Return a C++ dictionary
| |
| ggeett__lliisstt(...) | ggeett__lliisstt(...) from builtins.PyCapsule
| Signature : (Example2) -> list | Signature : (example.Example2) -> list
| |
| Return a Python list | Return a Python list
| |
| ggeett__lliisstt__22(...) | ggeett__lliisstt__22(...) from builtins.PyCapsule
| Signature : (Example2) -> list<str> | Signature : (example.Example2) -> list<str>
| |
| Return a C++ list | Return a C++ list
| |
| ggeett__sseett(...) | ggeett__sseett(...) from builtins.PyCapsule
| Signature : (Example2) -> set | Signature : (example.Example2) -> set
| |
| Return a Python set | Return a Python set
| |
| ggeett__sseett22(...) | ggeett__sseett22(...) from builtins.PyCapsule
| Signature : (Example2) -> set | Signature : (example.Example2) -> set
| |
| Return a C++ set | Return a C++ set
| |
| ppaaiirr__ppaasssstthhrroouugghh(...) | nneeww__iinnssttaannccee(...) from builtins.PyCapsule
| Signature : (Example2, (bool, str)) -> (str, bool) | Signature : () -> example.Example2
|
| Return an instance
|
| ppaaiirr__ppaasssstthhrroouugghh(...) from builtins.PyCapsule
| Signature : (example.Example2, (bool, str)) -> (str, bool)
| |
| Return a pair in reversed order | Return a pair in reversed order
| |
| pprriinntt__ddiicctt(...) | pprriinntt__ddiicctt(...) from builtins.PyCapsule
| Signature : (Example2, dict) -> None | Signature : (example.Example2, dict) -> None
| |
| Print entries of a Python dictionary | Print entries of a Python dictionary
| |
| pprriinntt__ddiicctt__22(...) | pprriinntt__ddiicctt__22(...) from builtins.PyCapsule
| Signature : (Example2, dict<str, str>) -> None | Signature : (example.Example2, dict<str, str>) -> None
| |
| Print entries of a C++ dictionary | Print entries of a C++ dictionary
| |
| pprriinntt__lliisstt(...) | pprriinntt__lliisstt(...) from builtins.PyCapsule
| Signature : (Example2, list) -> None | Signature : (example.Example2, list) -> None
| |
| Print entries of a Python list | Print entries of a Python list
| |
| pprriinntt__lliisstt__22(...) | pprriinntt__lliisstt__22(...) from builtins.PyCapsule
| Signature : (Example2, list<str>) -> None | Signature : (example.Example2, list<str>) -> None
| |
| Print entries of a C++ list | Print entries of a C++ list
| |
| pprriinntt__sseett(...) | pprriinntt__sseett(...) from builtins.PyCapsule
| Signature : (Example2, set) -> None | Signature : (example.Example2, set) -> None
| |
| Print entries of a Python set | Print entries of a Python set
| |
| pprriinntt__sseett__22(...) | pprriinntt__sseett__22(...) from builtins.PyCapsule
| Signature : (Example2, set<str>) -> None | Signature : (example.Example2, set<str>) -> None
| |
| Print entries of a C++ set | Print entries of a C++ set
| |
| tthhrrooww__eexxcceeppttiioonn(...) | tthhrrooww__eexxcceeppttiioonn(...) from builtins.PyCapsule
| Signature : (Example2) -> None | Signature : (example.Example2) -> None
| |
| Throw an exception | Throw an exception
| |
| ttuuppllee__ppaasssstthhrroouugghh(...) | ttuuppllee__ppaasssstthhrroouugghh(...) from builtins.PyCapsule
| Signature : (Example2, (bool, str, int32_t)) -> (int32_t, str, bool) | Signature : (example.Example2, (bool, str, int)) -> (int, str, bool)
| |
| Return a triple in reversed order | Return a triple in reversed order
| |
| ---------------------------------------------------------------------- | ----------------------------------------------------------------------
| Data and other attributes defined here: | Data and other attributes defined here:
| |
| ____nneeww____ = <built-in method __new__ of Example2_meta object>
| T.__new__(S, ...) -> a new object with type S, a subtype of T
|
| ____ppyybbiinndd1111____ = <capsule object NULL> | ____ppyybbiinndd1111____ = <capsule object NULL>
|
| nneeww__iinnssttaannccee = <built-in method new_instance of PyCapsule object>
| Signature : () -> Example2
|
| Return an instance
Destructing Example2 Destructing Example2

View File

@ -191,7 +191,7 @@ protected:
}; };
/// Generic type caster for objects stored on the heap /// Generic type caster for objects stored on the heap
template <typename type> class type_caster : public type_caster_custom { template <typename type, typename Enable = void> class type_caster : public type_caster_custom {
public: public:
static descr name() { return typeid(type); } static descr name() { return typeid(type); }
@ -229,49 +229,74 @@ protected:
operator type*() { return &value; } \ operator type*() { return &value; } \
operator type&() { return value; } operator type&() { return value; }
#define PYBIND11_TYPE_CASTER_NUMBER(type, py_type, from_type, to_pytype) \ template <typename T>
template <> class type_caster<type> { \ struct type_caster<
public: \ T, typename std::enable_if<std::is_integral<T>::value ||
bool load(PyObject *src, bool) { \ std::is_floating_point<T>::value>::type> {
py_type py_value = from_type(src); \ typedef typename std::conditional<sizeof(T) <= sizeof(long), long, long long>::type _py_type_0;
if ((py_value == (py_type) -1 && PyErr_Occurred()) || \ typedef typename std::conditional<std::is_signed<T>::value, _py_type_0, typename std::make_unsigned<_py_type_0>::type>::type _py_type_1;
(std::numeric_limits<type>::is_integer && \ typedef typename std::conditional<std::is_floating_point<T>::value, double, _py_type_1>::type py_type;
sizeof(py_type) != sizeof(type) && \ public:
(py_value < (py_type) std::numeric_limits<type>::min() || \
py_value > (py_type) std::numeric_limits<type>::max()))) { \
PyErr_Clear(); \
return false; \
} \
value = (type) py_value; \
return true; \
} \
static PyObject *cast(type src, return_value_policy /* policy */, PyObject * /* parent */) { \
return to_pytype((py_type) src); \
} \
PYBIND11_TYPE_CASTER(type, #type); \
};
PYBIND11_TYPE_CASTER_NUMBER(int8_t, long, PyLong_AsLong, PyLong_FromLong) bool load(PyObject *src, bool) {
PYBIND11_TYPE_CASTER_NUMBER(uint8_t, unsigned long, PyLong_AsUnsignedLong, PyLong_FromUnsignedLong) py_type py_value;
PYBIND11_TYPE_CASTER_NUMBER(int16_t, long, PyLong_AsLong, PyLong_FromLong)
PYBIND11_TYPE_CASTER_NUMBER(uint16_t, unsigned long, PyLong_AsUnsignedLong, PyLong_FromUnsignedLong)
PYBIND11_TYPE_CASTER_NUMBER(int32_t, long, PyLong_AsLong, PyLong_FromLong)
PYBIND11_TYPE_CASTER_NUMBER(uint32_t, unsigned long, PyLong_AsUnsignedLong, PyLong_FromUnsignedLong)
PYBIND11_TYPE_CASTER_NUMBER(int64_t, PY_LONG_LONG, detail::PyLong_AsLongLong, PyLong_FromLongLong)
PYBIND11_TYPE_CASTER_NUMBER(uint64_t, unsigned PY_LONG_LONG, detail::PyLong_AsUnsignedLongLong, PyLong_FromUnsignedLongLong)
#if defined(__APPLE__) // size_t/ssize_t are separate types on Mac OS X if (std::is_floating_point<T>::value) {
#if PY_MAJOR_VERSION >= 3 py_value = (py_type) PyFloat_AsDouble(src);
PYBIND11_TYPE_CASTER_NUMBER(ssize_t, Py_ssize_t, PyLong_AsSsize_t, PyLong_FromSsize_t) } else if (sizeof(T) <= sizeof(long)) {
PYBIND11_TYPE_CASTER_NUMBER(size_t, size_t, PyLong_AsSize_t, PyLong_FromSize_t) if (std::is_signed<T>::value)
#else py_value = (py_type) PyLong_AsLong(src);
PYBIND11_TYPE_CASTER_NUMBER(ssize_t, PY_LONG_LONG, detail::PyLong_AsLongLong, PyLong_FromLongLong) else
PYBIND11_TYPE_CASTER_NUMBER(size_t, unsigned PY_LONG_LONG, detail::PyLong_AsUnsignedLongLong, PyLong_FromUnsignedLongLong) py_value = (py_type) PyLong_AsUnsignedLong(src);
#endif } else {
#endif if (std::is_signed<T>::value)
py_value = (py_type) detail::PyLong_AsLongLong(src);
else
py_value = (py_type) detail::PyLong_AsUnsignedLongLong(src);
}
PYBIND11_TYPE_CASTER_NUMBER(float, double, PyFloat_AsDouble, PyFloat_FromDouble) if ((py_value == (py_type) -1 && PyErr_Occurred()) ||
PYBIND11_TYPE_CASTER_NUMBER(double, double, PyFloat_AsDouble, PyFloat_FromDouble) (std::is_integral<T>::value && sizeof(py_type) != sizeof(T) &&
(py_value < (py_type) std::numeric_limits<T>::min() ||
py_value > (py_type) std::numeric_limits<T>::max()))) {
PyErr_Clear();
return false;
}
value = (T) py_value;
return true;
}
static PyObject *cast(T src, return_value_policy /* policy */, PyObject * /* parent */) {
if (std::is_floating_point<T>::value) {
return PyFloat_FromDouble((double) src);
} else if (sizeof(T) <= sizeof(long)) {
if (std::is_signed<T>::value)
return PyLong_FromLong((long) src);
else
return PyLong_FromUnsignedLong((unsigned long) src);
} else {
if (std::is_signed<T>::value)
return PyLong_FromLongLong((long long) src);
else
return PyLong_FromUnsignedLongLong((unsigned long long) src);
}
}
static PyObject *cast(const T *src, return_value_policy policy, PyObject *parent) {
return cast(*src, policy, parent);
}
static descr name() {
return std::is_floating_point<T>::value ? "float" : "int";
}
operator T*() { return &value; }
operator T&() { return value; }
protected:
T value;
};
template <> class type_caster<void_type> { template <> class type_caster<void_type> {
public: public:

View File

@ -11,6 +11,7 @@
#include "common.h" #include "common.h"
#include <utility> #include <utility>
#include <type_traits>
NAMESPACE_BEGIN(pybind11) NAMESPACE_BEGIN(pybind11)
@ -213,16 +214,16 @@ private:
using ::PyLong_AsUnsignedLongLong; using ::PyLong_AsUnsignedLongLong;
using ::PyLong_AsLongLong; using ::PyLong_AsLongLong;
#else #else
inline PY_LONG_LONG PyLong_AsLongLong(PyObject *o) { inline long long PyLong_AsLongLong(PyObject *o) {
if (PyInt_Check(o)) if (PyInt_Check(o)) /// workaround: PyLong_AsLongLong doesn't accept 'int' on Python 2.x
return (PY_LONG_LONG) PyLong_AsLong(o); return (long long) PyLong_AsLong(o);
else else
return ::PyLong_AsLongLong(o); return ::PyLong_AsLongLong(o);
} }
inline unsigned PY_LONG_LONG PyLong_AsUnsignedLongLong(PyObject *o) { inline unsigned long long PyLong_AsUnsignedLongLong(PyObject *o) {
if (PyInt_Check(o)) if (PyInt_Check(o)) /// workaround: PyLong_AsUnsignedLongLong doesn't accept 'int' on Python 2.x
return (unsigned PY_LONG_LONG) PyLong_AsUnsignedLong(o); return (unsigned long long) PyLong_AsUnsignedLong(o);
else else
return ::PyLong_AsUnsignedLongLong(o); return ::PyLong_AsUnsignedLongLong(o);
} }
@ -291,27 +292,37 @@ public:
class int_ : public object { class int_ : public object {
public: public:
PYBIND11_OBJECT_DEFAULT(int_, object, PyLong_Check) PYBIND11_OBJECT_DEFAULT(int_, object, PyLong_Check)
int_(int32_t value) : object(PyLong_FromLong((long) value), false) { } template <typename T,
int_(int64_t value) : object(PyLong_FromLongLong((long long) value), false) { } typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
int_(uint32_t value) : object(PyLong_FromUnsignedLong((unsigned long) value), false) { } int_(T value) {
int_(uint64_t value) : object(PyLong_FromUnsignedLongLong((unsigned long long) value), false) { } if (sizeof(T) <= sizeof(long)) {
operator int32_t() const { return (int32_t) PyLong_AsLong(m_ptr); } if (std::is_signed<T>::value)
operator uint32_t() const { return (uint32_t) PyLong_AsUnsignedLong(m_ptr); } m_ptr = PyLong_FromLong((long) value);
operator int64_t() const { return (int64_t) detail::PyLong_AsLongLong(m_ptr); } else
operator uint64_t() const { return (uint64_t) detail::PyLong_AsUnsignedLongLong(m_ptr); } m_ptr = PyLong_FromUnsignedLong((unsigned long) value);
#if defined(__APPLE__) // size_t/ssize_t are separate types on Mac OS X } else {
#if PY_MAJOR_VERSION >= 3 if (std::is_signed<T>::value)
int_(size_t value) : object(PyLong_FromSize_t(value), false) { } m_ptr = PyLong_FromLongLong((long long) value);
int_(ssize_t value) : object(PyLong_FromSsize_t(value), false) { } else
operator size_t() const { return (size_t) PyLong_AsSize_t(m_ptr); } m_ptr = PyLong_FromUnsignedLongLong((unsigned long long) value);
operator ssize_t() const { return (ssize_t) PyLong_AsSsize_t(m_ptr); } }
#else }
int_(size_t value) : object(PyLong_FromUnsignedLongLong((unsigned long long) value), false) { }
int_(ssize_t value) : object(PyLong_FromLongLong((long long) value), false) { } template <typename T,
operator size_t() const { return (size_t) detail::PyLong_AsUnsignedLongLong(m_ptr); } typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
operator ssize_t() const { return (ssize_t) detail::PyLong_AsLongLong(m_ptr); } operator T() const {
#endif if (sizeof(T) <= sizeof(long)) {
#endif if (std::is_signed<T>::value)
return (T) PyLong_AsLong(m_ptr);
else
return (T) PyLong_AsUnsignedLong(m_ptr);
} else {
if (std::is_signed<T>::value)
return (T) detail::PyLong_AsLongLong(m_ptr);
else
return (T) detail::PyLong_AsUnsignedLongLong(m_ptr);
}
}
}; };
class float_ : public object { class float_ : public object {