Skip to content

Commit 60c36db

Browse files
author
Wenzel Jakob
committed
generic integer type handling
1 parent 7f8d1c2 commit 60c36db

File tree

4 files changed

+161
-127
lines changed

4 files changed

+161
-127
lines changed

example/example11.ref

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,3 @@
1-
Help on built-in function kw_func
2-
3-
kkww__ffuunncc(...)
4-
Signature : (x : int32_t, y : int32_t) -> None
5-
6-
Help on built-in function kw_func2
7-
8-
kkww__ffuunncc22(...)
9-
Signature : (x : int32_t = 100, y : int32_t = 200) -> None
10-
111
kw_func(x=5, y=10)
122
kw_func(x=5, y=10)
133
kw_func(x=5, y=10)
@@ -17,3 +7,13 @@ kw_func(x=5, y=200)
177
kw_func(x=100, y=10)
188
kw_func(x=5, y=10)
199
kw_func(x=5, y=10)
10+
Help on built-in function kw_func
11+
12+
kkww__ffuunncc(...) method of builtins.PyCapsule instance
13+
Signature : (x : int, y : int) -> None
14+
15+
Help on built-in function kw_func2
16+
17+
kkww__ffuunncc22(...) method of builtins.PyCapsule instance
18+
Signature : (x : int = 100, y : int = 200) -> None
19+

example/example2.ref

Lines changed: 47 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
15
2-
5
3-
Example2: No constructor defined!
4-
can't set attribute
5-
key: key2, value=value2
61
key: key, value=value
2+
key: key2, value=value2
73
key: key, value=value
84
key: key2, value=value2
95
key: key3
10-
key: key2
116
key: key1
7+
key: key2
128
key: key1
139
key: key2
1410
key: key3
@@ -17,105 +13,107 @@ list item 0: overwritten
1713
list item 1: value2
1814
list item 0: value
1915
list item 1: value2
16+
15
17+
5
18+
example.Example2: No constructor defined!
19+
can't set attribute
2020
This exception was intentionally thrown.
21-
(u'test', True)
22-
(5L, u'test', True)
21+
('test', True)
22+
(5, 'test', True)
2323
Help on class Example2 in module example
2424

25-
class EExxaammppllee22(__builtin__.object)
25+
class EExxaammppllee22(builtins.object)
2626
| Example 2 documentation
2727
|
2828
| Methods defined here:
2929
|
30-
| ____iinniitt____(...)
31-
| x.__init__(...) initializes x; see help(type(x)) for signature
30+
| ____iinniitt____(self, /, *args, **kwargs)
31+
| Initialize self. See help(type(self)) for accurate signature.
3232
|
33-
| ggeett__ddiicctt(...)
34-
| Signature : (Example2) -> dict
33+
| ____nneeww____ = <built-in method __new__ of example.Example2_meta object>
34+
| ggeett__ddiicctt(...) from builtins.PyCapsule
35+
| Signature : (example.Example2) -> dict
3536
|
3637
| Return a Python dictionary
3738
|
38-
| ggeett__ddiicctt__22(...)
39-
| Signature : (Example2) -> dict<str, str>
39+
| ggeett__ddiicctt__22(...) from builtins.PyCapsule
40+
| Signature : (example.Example2) -> dict<str, str>
4041
|
4142
| Return a C++ dictionary
4243
|
43-
| ggeett__lliisstt(...)
44-
| Signature : (Example2) -> list
44+
| ggeett__lliisstt(...) from builtins.PyCapsule
45+
| Signature : (example.Example2) -> list
4546
|
4647
| Return a Python list
4748
|
48-
| ggeett__lliisstt__22(...)
49-
| Signature : (Example2) -> list<str>
49+
| ggeett__lliisstt__22(...) from builtins.PyCapsule
50+
| Signature : (example.Example2) -> list<str>
5051
|
5152
| Return a C++ list
5253
|
53-
| ggeett__sseett(...)
54-
| Signature : (Example2) -> set
54+
| ggeett__sseett(...) from builtins.PyCapsule
55+
| Signature : (example.Example2) -> set
5556
|
5657
| Return a Python set
5758
|
58-
| ggeett__sseett22(...)
59-
| Signature : (Example2) -> set
59+
| ggeett__sseett22(...) from builtins.PyCapsule
60+
| Signature : (example.Example2) -> set
6061
|
6162
| Return a C++ set
6263
|
63-
| ppaaiirr__ppaasssstthhrroouugghh(...)
64-
| Signature : (Example2, (bool, str)) -> (str, bool)
64+
| nneeww__iinnssttaannccee(...) from builtins.PyCapsule
65+
| Signature : () -> example.Example2
66+
|
67+
| Return an instance
68+
|
69+
| ppaaiirr__ppaasssstthhrroouugghh(...) from builtins.PyCapsule
70+
| Signature : (example.Example2, (bool, str)) -> (str, bool)
6571
|
6672
| Return a pair in reversed order
6773
|
68-
| pprriinntt__ddiicctt(...)
69-
| Signature : (Example2, dict) -> None
74+
| pprriinntt__ddiicctt(...) from builtins.PyCapsule
75+
| Signature : (example.Example2, dict) -> None
7076
|
7177
| Print entries of a Python dictionary
7278
|
73-
| pprriinntt__ddiicctt__22(...)
74-
| Signature : (Example2, dict<str, str>) -> None
79+
| pprriinntt__ddiicctt__22(...) from builtins.PyCapsule
80+
| Signature : (example.Example2, dict<str, str>) -> None
7581
|
7682
| Print entries of a C++ dictionary
7783
|
78-
| pprriinntt__lliisstt(...)
79-
| Signature : (Example2, list) -> None
84+
| pprriinntt__lliisstt(...) from builtins.PyCapsule
85+
| Signature : (example.Example2, list) -> None
8086
|
8187
| Print entries of a Python list
8288
|
83-
| pprriinntt__lliisstt__22(...)
84-
| Signature : (Example2, list<str>) -> None
89+
| pprriinntt__lliisstt__22(...) from builtins.PyCapsule
90+
| Signature : (example.Example2, list<str>) -> None
8591
|
8692
| Print entries of a C++ list
8793
|
88-
| pprriinntt__sseett(...)
89-
| Signature : (Example2, set) -> None
94+
| pprriinntt__sseett(...) from builtins.PyCapsule
95+
| Signature : (example.Example2, set) -> None
9096
|
9197
| Print entries of a Python set
9298
|
93-
| pprriinntt__sseett__22(...)
94-
| Signature : (Example2, set<str>) -> None
99+
| pprriinntt__sseett__22(...) from builtins.PyCapsule
100+
| Signature : (example.Example2, set<str>) -> None
95101
|
96102
| Print entries of a C++ set
97103
|
98-
| tthhrrooww__eexxcceeppttiioonn(...)
99-
| Signature : (Example2) -> None
104+
| tthhrrooww__eexxcceeppttiioonn(...) from builtins.PyCapsule
105+
| Signature : (example.Example2) -> None
100106
|
101107
| Throw an exception
102108
|
103-
| ttuuppllee__ppaasssstthhrroouugghh(...)
104-
| Signature : (Example2, (bool, str, int32_t)) -> (int32_t, str, bool)
109+
| ttuuppllee__ppaasssstthhrroouugghh(...) from builtins.PyCapsule
110+
| Signature : (example.Example2, (bool, str, int)) -> (int, str, bool)
105111
|
106112
| Return a triple in reversed order
107113
|
108114
| ----------------------------------------------------------------------
109115
| Data and other attributes defined here:
110116
|
111-
| ____nneeww____ = <built-in method __new__ of Example2_meta object>
112-
| T.__new__(S, ...) -> a new object with type S, a subtype of T
113-
|
114117
| ____ppyybbiinndd1111____ = <capsule object NULL>
115-
|
116-
| nneeww__iinnssttaannccee = <built-in method new_instance of PyCapsule object>
117-
| Signature : () -> Example2
118-
|
119-
| Return an instance
120118

121119
Destructing Example2

include/pybind11/cast.h

Lines changed: 66 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ class type_caster_custom {
191191
};
192192

193193
/// Generic type caster for objects stored on the heap
194-
template <typename type> class type_caster : public type_caster_custom {
194+
template <typename type, typename Enable = void> class type_caster : public type_caster_custom {
195195
public:
196196
static descr name() { return typeid(type); }
197197

@@ -229,49 +229,74 @@ template <typename type> class type_caster : public type_caster_custom {
229229
operator type*() { return &value; } \
230230
operator type&() { return value; }
231231

232-
#define PYBIND11_TYPE_CASTER_NUMBER(type, py_type, from_type, to_pytype) \
233-
template <> class type_caster<type> { \
234-
public: \
235-
bool load(PyObject *src, bool) { \
236-
py_type py_value = from_type(src); \
237-
if ((py_value == (py_type) -1 && PyErr_Occurred()) || \
238-
(std::numeric_limits<type>::is_integer && \
239-
sizeof(py_type) != sizeof(type) && \
240-
(py_value < (py_type) std::numeric_limits<type>::min() || \
241-
py_value > (py_type) std::numeric_limits<type>::max()))) { \
242-
PyErr_Clear(); \
243-
return false; \
244-
} \
245-
value = (type) py_value; \
246-
return true; \
247-
} \
248-
static PyObject *cast(type src, return_value_policy /* policy */, PyObject * /* parent */) { \
249-
return to_pytype((py_type) src); \
250-
} \
251-
PYBIND11_TYPE_CASTER(type, #type); \
252-
};
232+
template <typename T>
233+
struct type_caster<
234+
T, typename std::enable_if<std::is_integral<T>::value ||
235+
std::is_floating_point<T>::value>::type> {
236+
typedef typename std::conditional<sizeof(T) <= sizeof(long), long, long long>::type _py_type_0;
237+
typedef typename std::conditional<std::is_signed<T>::value, _py_type_0, typename std::make_unsigned<_py_type_0>::type>::type _py_type_1;
238+
typedef typename std::conditional<std::is_floating_point<T>::value, double, _py_type_1>::type py_type;
239+
public:
253240

254-
PYBIND11_TYPE_CASTER_NUMBER(int8_t, long, PyLong_AsLong, PyLong_FromLong)
255-
PYBIND11_TYPE_CASTER_NUMBER(uint8_t, unsigned long, PyLong_AsUnsignedLong, PyLong_FromUnsignedLong)
256-
PYBIND11_TYPE_CASTER_NUMBER(int16_t, long, PyLong_AsLong, PyLong_FromLong)
257-
PYBIND11_TYPE_CASTER_NUMBER(uint16_t, unsigned long, PyLong_AsUnsignedLong, PyLong_FromUnsignedLong)
258-
PYBIND11_TYPE_CASTER_NUMBER(int32_t, long, PyLong_AsLong, PyLong_FromLong)
259-
PYBIND11_TYPE_CASTER_NUMBER(uint32_t, unsigned long, PyLong_AsUnsignedLong, PyLong_FromUnsignedLong)
260-
PYBIND11_TYPE_CASTER_NUMBER(int64_t, PY_LONG_LONG, detail::PyLong_AsLongLong, PyLong_FromLongLong)
261-
PYBIND11_TYPE_CASTER_NUMBER(uint64_t, unsigned PY_LONG_LONG, detail::PyLong_AsUnsignedLongLong, PyLong_FromUnsignedLongLong)
241+
bool load(PyObject *src, bool) {
242+
py_type py_value;
243+
244+
if (std::is_floating_point<T>::value) {
245+
py_value = (py_type) PyFloat_AsDouble(src);
246+
} else if (sizeof(T) <= sizeof(long)) {
247+
if (std::is_signed<T>::value)
248+
py_value = (py_type) PyLong_AsLong(src);
249+
else
250+
py_value = (py_type) PyLong_AsUnsignedLong(src);
251+
} else {
252+
if (std::is_signed<T>::value)
253+
py_value = (py_type) detail::PyLong_AsLongLong(src);
254+
else
255+
py_value = (py_type) detail::PyLong_AsUnsignedLongLong(src);
256+
}
262257

263-
#if defined(__APPLE__) // size_t/ssize_t are separate types on Mac OS X
264-
#if PY_MAJOR_VERSION >= 3
265-
PYBIND11_TYPE_CASTER_NUMBER(ssize_t, Py_ssize_t, PyLong_AsSsize_t, PyLong_FromSsize_t)
266-
PYBIND11_TYPE_CASTER_NUMBER(size_t, size_t, PyLong_AsSize_t, PyLong_FromSize_t)
267-
#else
268-
PYBIND11_TYPE_CASTER_NUMBER(ssize_t, PY_LONG_LONG, detail::PyLong_AsLongLong, PyLong_FromLongLong)
269-
PYBIND11_TYPE_CASTER_NUMBER(size_t, unsigned PY_LONG_LONG, detail::PyLong_AsUnsignedLongLong, PyLong_FromUnsignedLongLong)
270-
#endif
271-
#endif
258+
if ((py_value == (py_type) -1 && PyErr_Occurred()) ||
259+
(std::is_integral<T>::value && sizeof(py_type) != sizeof(T) &&
260+
(py_value < (py_type) std::numeric_limits<T>::min() ||
261+
py_value > (py_type) std::numeric_limits<T>::max()))) {
262+
PyErr_Clear();
263+
return false;
264+
}
272265

273-
PYBIND11_TYPE_CASTER_NUMBER(float, double, PyFloat_AsDouble, PyFloat_FromDouble)
274-
PYBIND11_TYPE_CASTER_NUMBER(double, double, PyFloat_AsDouble, PyFloat_FromDouble)
266+
value = (T) py_value;
267+
return true;
268+
}
269+
270+
static PyObject *cast(T src, return_value_policy /* policy */, PyObject * /* parent */) {
271+
if (std::is_floating_point<T>::value) {
272+
return PyFloat_FromDouble((double) src);
273+
} else if (sizeof(T) <= sizeof(long)) {
274+
if (std::is_signed<T>::value)
275+
return PyLong_FromLong((long) src);
276+
else
277+
return PyLong_FromUnsignedLong((unsigned long) src);
278+
} else {
279+
if (std::is_signed<T>::value)
280+
return PyLong_FromLongLong((long long) src);
281+
else
282+
return PyLong_FromUnsignedLongLong((unsigned long long) src);
283+
}
284+
}
285+
286+
static PyObject *cast(const T *src, return_value_policy policy, PyObject *parent) {
287+
return cast(*src, policy, parent);
288+
}
289+
290+
static descr name() {
291+
return std::is_floating_point<T>::value ? "float" : "int";
292+
}
293+
294+
operator T*() { return &value; }
295+
operator T&() { return value; }
296+
297+
protected:
298+
T value;
299+
};
275300

276301
template <> class type_caster<void_type> {
277302
public:

0 commit comments

Comments
 (0)