cast.h 20.1 KB
Newer Older
Wenzel Jakob's avatar
Wenzel Jakob committed
1
2
3
4
5
6
7
8
9
10
/*
    pybind/cast.h: Partial template specializations to cast between
    C++ and Python types

    Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>

    All rights reserved. Use of this source code is governed by a
    BSD-style license that can be found in the LICENSE file.
*/

11
#pragma once
Wenzel Jakob's avatar
Wenzel Jakob committed
12

13
14
#include <pybind/pytypes.h>
#include <pybind/typeid.h>
Wenzel Jakob's avatar
Wenzel Jakob committed
15
16
17
18
19
#include <array>

NAMESPACE_BEGIN(pybind)
NAMESPACE_BEGIN(detail)

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#if defined(_MSC_VER)
#define NOINLINE __declspec(noinline)
#else
#define NOINLINE __attribute__ ((noinline))
#endif

/** Linked list descriptor type for function signatures (produces smaller binaries
 * compared to a previous solution using std::string and operator +=) */
class descr {
public:
    struct entry {
        const std::type_info *type = nullptr;
        const char *str = nullptr;
        entry *next = nullptr;
        entry(const std::type_info *type) : type(type) { }
        entry(const char *str) : str(str) { }
    };

    descr() { }
    descr(descr &&d) : first(d.first), last(d.last) { d.first = d.last = nullptr; }
    NOINLINE descr(const char *str) { first = last = new entry { str }; }
    NOINLINE descr(const std::type_info &type) { first = last = new entry { &type }; }

    NOINLINE void operator+(const char *str) {
        entry *next = new entry { str };
        last->next = next;
        last = next;
    }

    NOINLINE void operator+(const std::type_info *type) {
        entry *next = new entry { type };
        last->next = next;
        last = next;
    }

    NOINLINE void operator+=(descr &&other) {
        last->next = other.first;
        while (last->next)
            last = last->next;
        other.first = other.last = nullptr;
    }

    NOINLINE friend descr operator+(descr &&l, descr &&r) {
        descr result(std::move(l));
        result += std::move(r);
        return result;
    }

    NOINLINE std::string str() const {
        std::string result;
        auto const& registered_types = get_internals().registered_types;
        for (entry *it = first; it != nullptr; it = it->next) {
            if (it->type) {
                auto it2 = registered_types.find(it->type);
                if (it2 != registered_types.end()) {
                    result += it2->second.type->tp_name;
                } else {
                    std::string tname(it->type->name());
                    detail::clean_type_id(tname);
                    result += tname;
                }
            } else {
                result += it->str;
            }
        }
        return result;
    }

    NOINLINE ~descr() {
        while (first) {
            entry *tmp = first->next;
            delete first;
            first = tmp;
        }
    }

    entry *first = nullptr;
    entry *last = nullptr;
};

#undef NOINLINE

Wenzel Jakob's avatar
Wenzel Jakob committed
102
103
104
105
106
/// Generic type caster for objects stored on the heap
template <typename type> class type_caster {
public:
    typedef instance<type> instance_type;

107
    static descr descr() { return typeid(type); }
Wenzel Jakob's avatar
Wenzel Jakob committed
108
109
110

    type_caster() {
        auto const& registered_types = get_internals().registered_types;
111
        auto it = registered_types.find(&typeid(type));
Wenzel Jakob's avatar
Wenzel Jakob committed
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
        if (it != registered_types.end())
            typeinfo = &it->second;
    }

    bool load(PyObject *src, bool convert) {
        if (src == nullptr || typeinfo == nullptr)
            return false;
        if (PyType_IsSubtype(Py_TYPE(src), typeinfo->type)) {
            value = ((instance_type *) src)->value;
            return true;
        }
        if (convert) {
            for (auto &converter : typeinfo->implicit_conversions) {
                temp = object(converter(src, typeinfo->type), false);
                if (load(temp.ptr(), false))
                    return true;
            }
        }
        return false;
    }

    static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
        if (policy == return_value_policy::automatic)
            policy = return_value_policy::copy;
        return cast(&src, policy, parent);
    }

    static PyObject *cast(const type *_src, return_value_policy policy, PyObject *parent) {
        type *src = const_cast<type *>(_src);
        if (src == nullptr) {
            Py_INCREF(Py_None);
            return Py_None;
        }
        // avoid an issue with internal references matching their parent's address
Wenzel Jakob's avatar
Wenzel Jakob committed
146
147
        bool dont_cache = policy == return_value_policy::reference_internal &&
                          parent && ((instance<void> *) parent)->value == (void *) src;
Wenzel Jakob's avatar
Wenzel Jakob committed
148
149
150
151
152
153
154
        auto& internals = get_internals();
        auto it_instance = internals.registered_instances.find(src);
        if (it_instance != internals.registered_instances.end() && !dont_cache) {
            PyObject *inst = it_instance->second;
            Py_INCREF(inst);
            return inst;
        }
155
        auto it = internals.registered_types.find(&typeid(type));
Wenzel Jakob's avatar
Wenzel Jakob committed
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
        if (it == internals.registered_types.end()) {
            std::string msg = std::string("Unregistered type : ") + type_id<type>();
            PyErr_SetString(PyExc_TypeError, msg.c_str());
            return nullptr;
        }
        auto &type_info = it->second;
        instance_type *inst = (instance_type *) PyType_GenericAlloc(type_info.type, 0);
        inst->value = src;
        inst->owned = true;
        inst->parent = nullptr;
        if (policy == return_value_policy::automatic)
            policy = return_value_policy::take_ownership;
        handle_return_value_policy<type>(inst, policy, parent);
        PyObject *inst_pyobj = (PyObject *) inst;
        type_info.init_holder(inst_pyobj);
        if (!dont_cache)
            internals.registered_instances[inst->value] = inst_pyobj;
        return inst_pyobj;
    }

    template <class T, typename std::enable_if<std::is_copy_constructible<T>::value, int>::type = 0>
    static void handle_return_value_policy(instance<T> *inst, return_value_policy policy, PyObject *parent) {
        if (policy == return_value_policy::copy) {
            inst->value = new T(*(inst->value));
        } else if (policy == return_value_policy::reference) {
            inst->owned = false;
        } else if (policy == return_value_policy::reference_internal) {
            inst->owned = false;
            inst->parent = parent;
            Py_XINCREF(parent);
        }
    }

    template <class T, typename std::enable_if<!std::is_copy_constructible<T>::value, int>::type = 0>
    static void handle_return_value_policy(instance<T> *inst, return_value_policy policy, PyObject *parent) {
        if (policy == return_value_policy::copy) {
            throw cast_error("return_value_policy = copy, but the object is non-copyable!");
        } else if (policy == return_value_policy::reference) {
            inst->owned = false;
        } else if (policy == return_value_policy::reference_internal) {
            inst->owned = false;
            inst->parent = parent;
            Py_XINCREF(parent);
        }
    }

    operator type*() { return value; }
    operator type&() { return *value; }
protected:
    type *value = nullptr;
    const type_info *typeinfo = nullptr;
    object temp;
};

Wenzel Jakob's avatar
Wenzel Jakob committed
210
#define PYBIND_TYPE_CASTER(type, py_name) \
Wenzel Jakob's avatar
Wenzel Jakob committed
211
212
213
    protected: \
        type value; \
    public: \
214
        static descr descr() { return py_name; } \
Wenzel Jakob's avatar
Wenzel Jakob committed
215
216
217
218
219
220
        static PyObject *cast(const type *src, return_value_policy policy, PyObject *parent) { \
            return cast(*src, policy, parent); \
        } \
        operator type*() { return &value; } \
        operator type&() { return value; } \

Wenzel Jakob's avatar
Wenzel Jakob committed
221
#define PYBIND_TYPE_CASTER_NUMBER(type, py_type, from_type, to_pytype) \
Wenzel Jakob's avatar
Wenzel Jakob committed
222
223
224
    template <> class type_caster<type> { \
    public: \
        bool load(PyObject *src, bool) { \
Wenzel Jakob's avatar
Wenzel Jakob committed
225
226
227
228
            py_type py_value = from_type(src); \
            if ((py_value == (py_type) -1 && PyErr_Occurred()) || \
                py_value < std::numeric_limits<type>::min() || \
                py_value > std::numeric_limits<type>::max()) { \
Wenzel Jakob's avatar
Wenzel Jakob committed
229
230
231
                PyErr_Clear(); \
                return false; \
            } \
Wenzel Jakob's avatar
Wenzel Jakob committed
232
            value = (type) py_value; \
Wenzel Jakob's avatar
Wenzel Jakob committed
233
234
235
236
237
            return true; \
        } \
        static PyObject *cast(type src, return_value_policy /* policy */, PyObject * /* parent */) { \
            return to_pytype((py_type) src); \
        } \
Wenzel Jakob's avatar
Wenzel Jakob committed
238
        PYBIND_TYPE_CASTER(type, #type); \
Wenzel Jakob's avatar
Wenzel Jakob committed
239
240
    };

Wenzel Jakob's avatar
Wenzel Jakob committed
241
242
243
244
PYBIND_TYPE_CASTER_NUMBER(int8_t, long, PyLong_AsLong, PyLong_FromLong)
PYBIND_TYPE_CASTER_NUMBER(uint8_t, unsigned long, PyLong_AsUnsignedLong, PyLong_FromUnsignedLong)
PYBIND_TYPE_CASTER_NUMBER(int16_t, long, PyLong_AsLong, PyLong_FromLong)
PYBIND_TYPE_CASTER_NUMBER(uint16_t, unsigned long, PyLong_AsUnsignedLong, PyLong_FromUnsignedLong)
Wenzel Jakob's avatar
Wenzel Jakob committed
245
246
247
248
PYBIND_TYPE_CASTER_NUMBER(int32_t, long, PyLong_AsLong, PyLong_FromLong)
PYBIND_TYPE_CASTER_NUMBER(uint32_t, unsigned long, PyLong_AsUnsignedLong, PyLong_FromUnsignedLong)
PYBIND_TYPE_CASTER_NUMBER(int64_t, PY_LONG_LONG, PyLong_AsLongLong, PyLong_FromLongLong)
PYBIND_TYPE_CASTER_NUMBER(uint64_t, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong, PyLong_FromUnsignedLongLong)
Wenzel Jakob's avatar
Wenzel Jakob committed
249
250

#if defined(__APPLE__) // size_t/ssize_t are separate types on Mac OS X
Wenzel Jakob's avatar
Wenzel Jakob committed
251
252
PYBIND_TYPE_CASTER_NUMBER(ssize_t, Py_ssize_t, PyLong_AsSsize_t, PyLong_FromSsize_t)
PYBIND_TYPE_CASTER_NUMBER(size_t, size_t, PyLong_AsSize_t, PyLong_FromSize_t)
Wenzel Jakob's avatar
Wenzel Jakob committed
253
254
#endif

Wenzel Jakob's avatar
Wenzel Jakob committed
255
256
PYBIND_TYPE_CASTER_NUMBER(float, float, PyFloat_AsDouble, PyFloat_FromDouble)
PYBIND_TYPE_CASTER_NUMBER(double, double, PyFloat_AsDouble, PyFloat_FromDouble)
Wenzel Jakob's avatar
Wenzel Jakob committed
257

258
template <> class type_caster<void_type> {
Wenzel Jakob's avatar
Wenzel Jakob committed
259
260
public:
    bool load(PyObject *, bool) { return true; }
261
    static PyObject *cast(void_type, return_value_policy /* policy */, PyObject * /* parent */) {
Wenzel Jakob's avatar
Wenzel Jakob committed
262
263
264
        Py_INCREF(Py_None);
        return Py_None;
    }
265
    PYBIND_TYPE_CASTER(void_type, "None");
Wenzel Jakob's avatar
Wenzel Jakob committed
266
267
268
269
270
271
272
273
274
275
276
277
278
279
};

template <> class type_caster<bool> {
public:
    bool load(PyObject *src, bool) {
        if (src == Py_True) { value = true; return true; }
        else if (src == Py_False) { value = false; return true; }
        else return false;
    }
    static PyObject *cast(bool src, return_value_policy /* policy */, PyObject * /* parent */) {
        PyObject *result = src ? Py_True : Py_False;
        Py_INCREF(result);
        return result;
    }
Wenzel Jakob's avatar
Wenzel Jakob committed
280
    PYBIND_TYPE_CASTER(bool, "bool");
Wenzel Jakob's avatar
Wenzel Jakob committed
281
282
283
284
285
286
287
288
289
290
291
292
293
};

template <> class type_caster<std::string> {
public:
    bool load(PyObject *src, bool) {
        const char *ptr = PyUnicode_AsUTF8(src);
        if (!ptr) { PyErr_Clear(); return false; }
        value = std::string(ptr);
        return true;
    }
    static PyObject *cast(const std::string &src, return_value_policy /* policy */, PyObject * /* parent */) {
        return PyUnicode_FromString(src.c_str());
    }
Wenzel Jakob's avatar
Wenzel Jakob committed
294
    PYBIND_TYPE_CASTER(std::string, "str");
Wenzel Jakob's avatar
Wenzel Jakob committed
295
296
};

Wenzel Jakob's avatar
Wenzel Jakob committed
297
298
299
300
301
302
303
304
305
306
307
308
#ifdef HAVE_WCHAR_H
template <> class type_caster<std::wstring> {
public:
    bool load(PyObject *src, bool) {
        const wchar_t *ptr = PyUnicode_AsWideCharString(src, nullptr);
        if (!ptr) { PyErr_Clear(); return false; }
        value = std::wstring(ptr);
        return true;
    }
    static PyObject *cast(const std::wstring &src, return_value_policy /* policy */, PyObject * /* parent */) {
        return PyUnicode_FromWideChar(src.c_str(), src.length());
    }
Wenzel Jakob's avatar
Wenzel Jakob committed
309
    PYBIND_TYPE_CASTER(std::wstring, "wstr");
Wenzel Jakob's avatar
Wenzel Jakob committed
310
311
312
};
#endif

Wenzel Jakob's avatar
Wenzel Jakob committed
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
template <> class type_caster<char> {
public:
    bool load(PyObject *src, bool) {
        char *ptr = PyUnicode_AsUTF8(src);
        if (!ptr) { PyErr_Clear(); return false; }
        value = ptr;
        return true;
    }

    static PyObject *cast(const char *src, return_value_policy /* policy */, PyObject * /* parent */) {
        return PyUnicode_FromString(src);
    }

    static PyObject *cast(char src, return_value_policy /* policy */, PyObject * /* parent */) {
        char str[2] = { src, '\0' };
        return PyUnicode_DecodeLatin1(str, 1, nullptr);
    }

331
    static descr descr() { return "str"; }
Wenzel Jakob's avatar
Wenzel Jakob committed
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350

    operator char*() { return value; }
    operator char() { return *value; }
protected:
    char *value;
};

template <typename T1, typename T2> class type_caster<std::pair<T1, T2>> {
    typedef std::pair<T1, T2> type;
public:
    bool load(PyObject *src, bool convert) {
        if (!PyTuple_Check(src) || PyTuple_Size(src) != 2)
            return false;
        if (!first.load(PyTuple_GetItem(src, 0), convert))
            return false;
        return second.load(PyTuple_GetItem(src, 1), convert);
    }

    static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
351
352
        PyObject *o1 = type_caster<typename decay<T1>::type>::cast(src.first, policy, parent);
        PyObject *o2 = type_caster<typename decay<T2>::type>::cast(src.second, policy, parent);
Wenzel Jakob's avatar
Wenzel Jakob committed
353
354
355
356
357
358
359
360
361
362
363
        if (!o1 || !o2) {
            Py_XDECREF(o1);
            Py_XDECREF(o2);
            return nullptr;
        }
        PyObject *tuple = PyTuple_New(2);
        PyTuple_SetItem(tuple, 0, o1);
        PyTuple_SetItem(tuple, 1, o2);
        return tuple;
    }

364
365
366
367
368
369
370
    static descr descr() {
        class descr result("(");
        result += std::move(type_caster<typename decay<T1>::type>::descr());
        result += ", ";
        result += std::move(type_caster<typename decay<T2>::type>::descr());
        result += ")";
        return result;
Wenzel Jakob's avatar
Wenzel Jakob committed
371
372
373
374
375
376
    }

    operator type() {
        return type(first, second);
    }
protected:
377
378
    type_caster<typename decay<T1>::type> first;
    type_caster<typename decay<T2>::type> second;
Wenzel Jakob's avatar
Wenzel Jakob committed
379
380
};

381
template <typename... Tuple> class type_caster<std::tuple<Tuple...>> {
Wenzel Jakob's avatar
Wenzel Jakob committed
382
383
384
385
386
    typedef std::tuple<Tuple...> type;
public:
    enum { size = sizeof...(Tuple) };

    bool load(PyObject *src, bool convert) {
Wenzel Jakob's avatar
Wenzel Jakob committed
387
        return load(src, convert, typename make_index_sequence<sizeof...(Tuple)>::type());
Wenzel Jakob's avatar
Wenzel Jakob committed
388
389
390
    }

    static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
Wenzel Jakob's avatar
Wenzel Jakob committed
391
        return cast(src, policy, parent, typename make_index_sequence<size>::type());
Wenzel Jakob's avatar
Wenzel Jakob committed
392
393
    }

394
395
396
    static descr descr(const char **keywords = nullptr, const char **values = nullptr) {
        std::array<class descr, size> descrs {{
            type_caster<typename decay<Tuple>::type>::descr()...
Wenzel Jakob's avatar
Wenzel Jakob committed
397
        }};
398
399
400
401
        class descr result("(");
        for (int i=0; i<size; ++i) {
            if (keywords && keywords[i]) {
                result += keywords[i];
402
403
                result += " : ";
            }
404
405
            result += std::move(descrs[i]);
            if (values && values[i]) {
406
                result += " = ";
407
                result += values[i];
408
            }
409
            if (i+1 < size)
Wenzel Jakob's avatar
Wenzel Jakob committed
410
411
412
413
414
415
                result += ", ";
        }
        result += ")";
        return result;
    }

416
417
    template <typename ReturnValue, typename Func> typename std::enable_if<!std::is_void<ReturnValue>::value, ReturnValue>::type call(Func &&f) {
        return call<ReturnValue>(std::forward<Func>(f), typename make_index_sequence<sizeof...(Tuple)>::type());
Wenzel Jakob's avatar
Wenzel Jakob committed
418
419
    }

420
    template <typename ReturnValue, typename Func> typename std::enable_if<std::is_void<ReturnValue>::value, void_type>::type call(Func &&f) {
421
        call<ReturnValue>(std::forward<Func>(f), typename make_index_sequence<sizeof...(Tuple)>::type());
422
        return void_type();
Wenzel Jakob's avatar
Wenzel Jakob committed
423
424
    }

Wenzel Jakob's avatar
Wenzel Jakob committed
425
    operator type() {
Wenzel Jakob's avatar
Wenzel Jakob committed
426
        return cast(typename make_index_sequence<sizeof...(Tuple)>::type());
Wenzel Jakob's avatar
Wenzel Jakob committed
427
    }
Wenzel Jakob's avatar
Wenzel Jakob committed
428

Wenzel Jakob's avatar
Wenzel Jakob committed
429
protected:
430
    template <typename ReturnValue, typename Func, size_t ... Index> ReturnValue call(Func &&f, index_sequence<Index...>) {
Wenzel Jakob's avatar
Wenzel Jakob committed
431
432
433
434
        return f((Tuple) std::get<Index>(value)...);
    }

    template <size_t ... Index> type cast(index_sequence<Index...>) {
Wenzel Jakob's avatar
Wenzel Jakob committed
435
436
437
        return type((Tuple) std::get<Index>(value)...);
    }

Wenzel Jakob's avatar
Wenzel Jakob committed
438
    template <size_t ... Indices> bool load(PyObject *src, bool convert, index_sequence<Indices...>) {
Wenzel Jakob's avatar
Wenzel Jakob committed
439
440
441
442
443
        if (!PyTuple_Check(src))
            return false;
        if (PyTuple_Size(src) != size)
            return false;
        std::array<bool, size> results {{
444
            (PyTuple_GET_ITEM(src, Indices) != nullptr ? std::get<Indices>(value).load(PyTuple_GET_ITEM(src, Indices), convert) : false)...
Wenzel Jakob's avatar
Wenzel Jakob committed
445
        }};
446
        (void) convert; /* avoid a warning when the tuple is empty */
Wenzel Jakob's avatar
Wenzel Jakob committed
447
448
449
450
451
452
453
        for (bool r : results)
            if (!r)
                return false;
        return true;
    }

    /* Implementation: Convert a C++ tuple into a Python tuple */
Wenzel Jakob's avatar
Wenzel Jakob committed
454
    template <size_t ... Indices> static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent, index_sequence<Indices...>) {
Wenzel Jakob's avatar
Wenzel Jakob committed
455
        std::array<PyObject *, size> results {{
456
            type_caster<typename decay<Tuple>::type>::cast(std::get<Indices>(src), policy, parent)...
Wenzel Jakob's avatar
Wenzel Jakob committed
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
        }};
        bool success = true;
        for (auto result : results)
            if (result == nullptr)
                success = false;
        if (success) {
            PyObject *tuple = PyTuple_New(size);
            int counter = 0;
            for (auto result : results)
                PyTuple_SetItem(tuple, counter++, result);
            return tuple;
        } else {
            for (auto result : results) {
                Py_XDECREF(result);
            }
            return nullptr;
        }
    }

protected:
477
    std::tuple<type_caster<typename decay<Tuple>::type>...> value;
Wenzel Jakob's avatar
Wenzel Jakob committed
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
};

/// Type caster for holder types like std::shared_ptr, etc.
template <typename type, typename holder_type> class type_caster_holder : public type_caster<type> {
public:
    typedef type_caster<type> parent;
    bool load(PyObject *src, bool convert) {
        if (!parent::load(src, convert))
            return false;
        holder = holder_type(parent::value);
        return true;
    }
    explicit operator type*() { return this->value; }
    explicit operator type&() { return *(this->value); }
    explicit operator holder_type&() { return holder; }
    explicit operator holder_type*() { return &holder; }
protected:
    holder_type holder;
};

template <> class type_caster<handle> {
public:
    bool load(PyObject *src) {
        value = handle(src);
        return true;
    }
    static PyObject *cast(const handle &src, return_value_policy /* policy */, PyObject * /* parent */) {
        src.inc_ref();
        return (PyObject *) src.ptr();
    }
Wenzel Jakob's avatar
Wenzel Jakob committed
508
    PYBIND_TYPE_CASTER(handle, "handle");
Wenzel Jakob's avatar
Wenzel Jakob committed
509
510
};

Wenzel Jakob's avatar
Wenzel Jakob committed
511
#define PYBIND_TYPE_CASTER_PYTYPE(name) \
Wenzel Jakob's avatar
Wenzel Jakob committed
512
513
514
515
516
517
    template <> class type_caster<name> { \
    public: \
        bool load(PyObject *src, bool) { value = name(src, true); return true; } \
        static PyObject *cast(const name &src, return_value_policy /* policy */, PyObject * /* parent */) { \
            src.inc_ref(); return (PyObject *) src.ptr(); \
        } \
Wenzel Jakob's avatar
Wenzel Jakob committed
518
        PYBIND_TYPE_CASTER(name, #name); \
Wenzel Jakob's avatar
Wenzel Jakob committed
519
520
    };

Wenzel Jakob's avatar
Wenzel Jakob committed
521
522
523
524
525
PYBIND_TYPE_CASTER_PYTYPE(object)  PYBIND_TYPE_CASTER_PYTYPE(buffer)
PYBIND_TYPE_CASTER_PYTYPE(capsule) PYBIND_TYPE_CASTER_PYTYPE(dict)
PYBIND_TYPE_CASTER_PYTYPE(float_)  PYBIND_TYPE_CASTER_PYTYPE(int_)
PYBIND_TYPE_CASTER_PYTYPE(list)    PYBIND_TYPE_CASTER_PYTYPE(slice)
PYBIND_TYPE_CASTER_PYTYPE(tuple)   PYBIND_TYPE_CASTER_PYTYPE(function)
Wenzel Jakob's avatar
Wenzel Jakob committed
526
527
528
529

NAMESPACE_END(detail)

template <typename T> inline T cast(PyObject *object) {
Wenzel Jakob's avatar
Wenzel Jakob committed
530
    detail::type_caster<typename detail::decay<T>::type> conv;
Wenzel Jakob's avatar
Wenzel Jakob committed
531
532
533
534
535
536
537
538
    if (!conv.load(object, true))
        throw cast_error("Unable to cast Python object to C++ type");
    return conv;
}

template <typename T> inline object cast(const T &value, return_value_policy policy = return_value_policy::automatic, PyObject *parent = nullptr) {
    if (policy == return_value_policy::automatic)
        policy = std::is_pointer<T>::value ? return_value_policy::take_ownership : return_value_policy::copy;
Wenzel Jakob's avatar
Wenzel Jakob committed
539
    return object(detail::type_caster<typename detail::decay<T>::type>::cast(value, policy, parent), false);
Wenzel Jakob's avatar
Wenzel Jakob committed
540
541
542
543
}

template <typename T> inline T handle::cast() { return pybind::cast<T>(m_ptr); }

544
template <typename... Args> inline object handle::call(Args&&... args_) {
Wenzel Jakob's avatar
Wenzel Jakob committed
545
546
    const size_t size = sizeof...(Args);
    std::array<PyObject *, size> args{
Wenzel Jakob's avatar
Wenzel Jakob committed
547
        { detail::type_caster<typename detail::decay<Args>::type>::cast(
Wenzel Jakob's avatar
Wenzel Jakob committed
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
            std::forward<Args>(args_), return_value_policy::automatic, nullptr)... }
    };
    bool fail = false;
    for (auto result : args)
        if (result == nullptr)
            fail = true;
    if (fail) {
        for (auto result : args) {
            Py_XDECREF(result);
        }
        throw cast_error("handle::call(): unable to convert input arguments to Python objects");
    }
    PyObject *tuple = PyTuple_New(size);
    int counter = 0;
    for (auto result : args)
        PyTuple_SetItem(tuple, counter++, result);
    PyObject *result = PyObject_CallObject(m_ptr, tuple);
    Py_DECREF(tuple);
    return object(result, false);
}

NAMESPACE_END(pybind)