pybind.h 29.6 KB
Newer Older
Wenzel Jakob's avatar
Wenzel Jakob committed
1
2
3
4
5
6
7
8
9
/*
    pybind/pybind.h: Main header file of the C++11 python binding generator library

    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.
*/

10
#pragma once
Wenzel Jakob's avatar
Wenzel Jakob committed
11
12
13
14
15
16
17
18
19
20

#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
#pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning)
#pragma warning(disable: 4996) // warning C4996: The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name
#pragma warning(disable: 4100) // warning C4100: Unreferenced formal parameter
#pragma warning(disable: 4512) // warning C4512: Assignment operator was implicitly defined as deleted
#endif

21
#include <pybind/cast.h>
Wenzel Jakob's avatar
Wenzel Jakob committed
22
23
24

NAMESPACE_BEGIN(pybind)

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
template <typename T> struct arg_t;

/// Annotation for keyword arguments
struct arg {
    arg(const char *name) : name(name) { }
    template <typename T> inline arg_t<T> operator=(const T &value);
    const char *name;
};

/// Annotation for keyword arguments with default values
template <typename T> struct arg_t : public arg {
    arg_t(const char *name, const T &value) : arg(name), value(value) { }
    T value;
};
template <typename T> inline arg_t<T> arg::operator=(const T &value) { return arg_t<T>(name, value); }

/// Annotation for methods
struct is_method { };

/// Annotation for documentation
struct doc { const char *value; doc(const char *value) : value(value) { } };

/// Annotation for function names
struct name { const char *value; name(const char *value) : value(value) { } };

/// Annotation for function siblings
struct sibling { PyObject *value; sibling(handle value) : value(value.ptr()) { } };

Wenzel Jakob's avatar
Wenzel Jakob committed
53
/// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object
54
class cpp_function : public function {
Wenzel Jakob's avatar
Wenzel Jakob committed
55
56
private:
    /// Chained list of function entries for overloading
Wenzel Jakob's avatar
Wenzel Jakob committed
57
    struct function_entry {
58
59
        const char *name = nullptr;
        PyObject * (*impl) (function_entry *, PyObject *, PyObject *, PyObject *);
Wenzel Jakob's avatar
Wenzel Jakob committed
60
        void *data;
61
62
63
64
65
66
        bool is_constructor = false, is_method = false;
        short keywords = 0;
        return_value_policy policy = return_value_policy::automatic;
        std::string signature;
        PyObject *sibling = nullptr;
        const char *doc = nullptr;
Wenzel Jakob's avatar
Wenzel Jakob committed
67
68
69
        function_entry *next = nullptr;
    };

Wenzel Jakob's avatar
Wenzel Jakob committed
70
71
72
73
74
75
    /// Picks a suitable return value converter from cast.h
    template <typename T> using return_value_caster =
        detail::type_caster<typename std::conditional<
            std::is_void<T>::value, detail::void_type, typename detail::decay<T>::type>::type>;

    /// Picks a suitable argument value converter from cast.h
76
    template <typename... T> using arg_value_caster =
Wenzel Jakob's avatar
Wenzel Jakob committed
77
        detail::type_caster<typename std::tuple<T...>>;
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98


    template <typename... T> void process_args(const std::tuple<T...> &args, function_entry *entry) {
        process_args(args, entry, typename detail::make_index_sequence<sizeof...(T)>::type());
    }

    template <typename... T, size_t ... Index> void process_args(const
            std::tuple<T...> &args, function_entry *entry,
            detail::index_sequence<Index...>) {
        int unused[] = { 0, (process_arg(std::get<Index>(args), entry), 0)... };
        (void) unused;
    }

    void process_arg(const char *doc, function_entry *entry) { entry->doc = doc; }
    void process_arg(const pybind::doc &d, function_entry *entry) { entry->doc = d.value; }
    void process_arg(const pybind::name &n, function_entry *entry) { entry->name = n.value; }
    void process_arg(const pybind::arg &, function_entry *entry) { entry->keywords++; }
    void process_arg(const pybind::is_method &, function_entry *entry) { entry->is_method = true; }
    void process_arg(const pybind::return_value_policy p, function_entry *entry) { entry->policy = p; }
    void process_arg(pybind::sibling s, function_entry *entry) { entry->sibling = s.value; }

Wenzel Jakob's avatar
Wenzel Jakob committed
99
public:
100
    cpp_function() { }
Wenzel Jakob's avatar
Wenzel Jakob committed
101
102

    /// Vanilla function pointers
103
104
105
106
107
108
    template <typename Return, typename... Arg, typename... Extra>
    cpp_function(Return (*f)(Arg...), Extra&&... extra) {
        struct capture {
            Return (*f)(Arg...);
            std::tuple<Extra...> extra;
        };
Wenzel Jakob's avatar
Wenzel Jakob committed
109

110
111
        function_entry *entry = new function_entry();
        entry->data = new capture { f, std::tuple<Extra...>(std::forward<Extra>(extra)...) };
Wenzel Jakob's avatar
Wenzel Jakob committed
112

113
114
115
116
        typedef arg_value_caster<Arg...> cast_in;
        typedef return_value_caster<Return> cast_out;

        entry->impl = [](function_entry *entry, PyObject *pyArgs, PyObject *kwargs, PyObject *parent) -> PyObject * {
Wenzel Jakob's avatar
Wenzel Jakob committed
117
            cast_in args;
Wenzel Jakob's avatar
Wenzel Jakob committed
118
            if (!args.load(pyArgs, true)) return nullptr;
119
120
121
            auto f = ((capture *) entry->data)->f;
            (void)kwargs;
            return cast_out::cast(args.template call<Return>(f), entry->policy, parent);
Wenzel Jakob's avatar
Wenzel Jakob committed
122
123
        };

124
125
126
127
128
        entry->signature = cast_in::name();
        entry->signature += " -> ";
        entry->signature += cast_out::name();
        process_args(((capture *) entry->data)->extra, entry);
        initialize(entry);
Wenzel Jakob's avatar
Wenzel Jakob committed
129
130
131
    }

    /// Delegating helper constructor to deal with lambda functions
132
133
    template <typename Func, typename... Extra> cpp_function(Func &&f, Extra&&... extra) {
        initialize(std::forward<Func>(f),
Wenzel Jakob's avatar
Wenzel Jakob committed
134
                   (typename detail::remove_class<decltype(
135
136
                       &std::remove_reference<Func>::type::operator())>::type *) nullptr,
                   std::forward<Extra>(extra)...);
Wenzel Jakob's avatar
Wenzel Jakob committed
137
138
139
140
    }


    /// Class methods (non-const)
141
142
143
144
    template <typename Return, typename Class, typename... Arg, typename... Extra> cpp_function(
            Return (Class::*f)(Arg...), Extra&&... extra) {
        initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); },
                   (Return (*) (Class *, Arg...)) nullptr, std::forward<Extra>(extra)...);
Wenzel Jakob's avatar
Wenzel Jakob committed
145
    }
Wenzel Jakob's avatar
Wenzel Jakob committed
146
147

    /// Class methods (const)
148
149
150
151
    template <typename Return, typename Class, typename... Arg, typename... Extra> cpp_function(
            Return (Class::*f)(Arg...) const, Extra&&... extra) {
        initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); },
                   (Return (*)(const Class *, Arg ...)) nullptr, std::forward<Extra>(extra)...);
Wenzel Jakob's avatar
Wenzel Jakob committed
152
153
    }

Wenzel Jakob's avatar
Wenzel Jakob committed
154
private:
Wenzel Jakob's avatar
Wenzel Jakob committed
155
    /// Functors, lambda functions, etc.
156
157
158
159
160
161
    template <typename Func, typename Return, typename... Arg, typename... Extra>
    void initialize(Func &&f, Return (*)(Arg...), Extra&&... extra) {
        struct capture {
            typename std::remove_reference<Func>::type f;
            std::tuple<Extra...> extra;
        };
Wenzel Jakob's avatar
Wenzel Jakob committed
162

163
164
165
166
167
        function_entry *entry = new function_entry();
        entry->data = new capture { std::forward<Func>(f), std::tuple<Extra...>(std::forward<Extra>(extra)...) };

        typedef arg_value_caster<Arg...> cast_in;
        typedef return_value_caster<Return> cast_out;
Wenzel Jakob's avatar
Wenzel Jakob committed
168

169
        entry->impl = [](function_entry *entry, PyObject *pyArgs, PyObject *kwargs, PyObject *parent) -> PyObject *{
Wenzel Jakob's avatar
Wenzel Jakob committed
170
171
            cast_in args;
            if (!args.load(pyArgs, true)) return nullptr;
172
173
174
            Func &f = ((capture *) entry->data)->f;
            (void)kwargs;
            return cast_out::cast(args.template call<Return>(f), entry->policy, parent);
Wenzel Jakob's avatar
Wenzel Jakob committed
175
176
        };

177
178
179
180
181
        entry->signature = cast_in::name();
        entry->signature += " -> ";
        entry->signature += cast_out::name();
        process_args(((capture *) entry->data)->extra, entry);
        initialize(entry);
Wenzel Jakob's avatar
Wenzel Jakob committed
182
183
    }

184
    static PyObject *dispatcher(PyObject *self, PyObject *args, PyObject *kwargs ) {
Wenzel Jakob's avatar
Wenzel Jakob committed
185
186
        function_entry *overloads = (function_entry *) PyCapsule_GetPointer(self, nullptr);
        PyObject *result = nullptr;
Wenzel Jakob's avatar
Wenzel Jakob committed
187
        PyObject *parent = PyTuple_Size(args) > 0 ? PyTuple_GetItem(args, 0) : nullptr;
Wenzel Jakob's avatar
Wenzel Jakob committed
188
189
        try {
            for (function_entry *it = overloads; it != nullptr; it = it->next) {
190
                if ((result = it->impl(it, args, kwargs, parent)) != nullptr)
Wenzel Jakob's avatar
Wenzel Jakob committed
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
                    break;
            }
        } catch (const error_already_set &) {                                               return nullptr;
        } catch (const index_error &e)    { PyErr_SetString(PyExc_IndexError,    e.what()); return nullptr;
        } catch (const stop_iteration &e) { PyErr_SetString(PyExc_StopIteration, e.what()); return nullptr;
        } catch (const std::exception &e) { PyErr_SetString(PyExc_RuntimeError,  e.what()); return nullptr;
        } catch (...) {
            PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!");
            return nullptr;
        }
        if (result) {
            if (overloads->is_constructor) {
                PyObject *inst = PyTuple_GetItem(args, 0);
                const detail::type_info *type_info =
                    capsule(PyObject_GetAttrString((PyObject *) Py_TYPE(inst),
                                const_cast<char *>("__pybind__")), false);
                type_info->init_holder(inst);
            }
            return result;
        } else {
            std::string signatures = "Incompatible function arguments. The "
                                     "following argument types are supported:\n";
            int ctr = 0;
            for (function_entry *it = overloads; it != nullptr; it = it->next) {
                signatures += "    "+ std::to_string(++ctr) + ". ";
                signatures += it->signature;
                signatures += "\n";
            }
            PyErr_SetString(PyExc_TypeError, signatures.c_str());
            return nullptr;
        }
    }

224
225
226
    void initialize(function_entry *entry) {
        if (entry->name == nullptr)
            entry->name = "";
227

228
229
230
        entry->is_constructor = !strcmp(entry->name, "__init__");

        if (!entry->sibling || !PyCFunction_Check(entry->sibling)) {
Wenzel Jakob's avatar
Wenzel Jakob committed
231
232
            PyMethodDef *def = new PyMethodDef();
            memset(def, 0, sizeof(PyMethodDef));
233
            def->ml_name = entry->name;
Wenzel Jakob's avatar
Wenzel Jakob committed
234
235
236
237
238
            def->ml_meth = reinterpret_cast<PyCFunction>(*dispatcher);
            def->ml_flags = METH_VARARGS | METH_KEYWORDS;
            capsule entry_capsule(entry);
            m_ptr = PyCFunction_New(def, entry_capsule.ptr());
            if (!m_ptr)
239
                throw std::runtime_error("cpp_function::cpp_function(): Could not allocate function object");
Wenzel Jakob's avatar
Wenzel Jakob committed
240
        } else {
241
            m_ptr = entry->sibling;
Wenzel Jakob's avatar
Wenzel Jakob committed
242
243
244
245
246
247
248
249
250
            inc_ref();
            capsule entry_capsule(PyCFunction_GetSelf(m_ptr), true);
            function_entry *parent = (function_entry *) entry_capsule, *backup = parent;
            while (parent->next)
                parent = parent->next;
            parent->next = entry;
            entry = backup;
        }
        std::string signatures;
251
252
253
254
255
256
257
258
259
        int index = 0;
        function_entry *it = entry;
        while (it) { /* Create pydoc it */
            if (it->sibling)
                signatures += std::to_string(++index) + ". ";
            signatures += "Signature : " + std::string(it->signature) + "\n";
            if (it->doc && strlen(it->doc) > 0)
                signatures += "\n" + std::string(it->doc) + "\n";
            if (it->next)
Wenzel Jakob's avatar
Wenzel Jakob committed
260
                signatures += "\n";
261
            it = it->next;
Wenzel Jakob's avatar
Wenzel Jakob committed
262
263
264
265
266
        }
        PyCFunctionObject *func = (PyCFunctionObject *) m_ptr;
        if (func->m_ml->ml_doc)
            std::free((char *) func->m_ml->ml_doc);
        func->m_ml->ml_doc = strdup(signatures.c_str());
267
        if (entry->is_method) {
Wenzel Jakob's avatar
Wenzel Jakob committed
268
269
            m_ptr = PyInstanceMethod_New(m_ptr);
            if (!m_ptr)
270
                throw std::runtime_error("cpp_function::cpp_function(): Could not allocate instance method object");
Wenzel Jakob's avatar
Wenzel Jakob committed
271
272
273
274
275
276
277
            Py_DECREF(func);
        }
    }
};

class module : public object {
public:
Wenzel Jakob's avatar
Wenzel Jakob committed
278
    PYBIND_OBJECT_DEFAULT(module, object, PyModule_Check)
Wenzel Jakob's avatar
Wenzel Jakob committed
279
280
281
282
283
284
285
286
287
288
289
290
291
292

    module(const char *name, const char *doc = nullptr) {
        PyModuleDef *def = new PyModuleDef();
        memset(def, 0, sizeof(PyModuleDef));
        def->m_name = name;
        def->m_doc = doc;
        def->m_size = -1;
        Py_INCREF(def);
        m_ptr = PyModule_Create(def);
        if (m_ptr == nullptr)
            throw std::runtime_error("Internal error in module::module()");
        inc_ref();
    }

293
294
295
296
    template <typename Func, typename... Extra>
    module &def(const char *name_, Func &&f, Extra&& ... extra) {
        cpp_function func(std::forward<Func>(f), name(name_),
                          sibling((handle) attr(name_)), std::forward<Extra>(extra)...);
Wenzel Jakob's avatar
Wenzel Jakob committed
297
        func.inc_ref(); /* The following line steals a reference to 'func' */
298
        PyModule_AddObject(ptr(), name_, func.ptr());
Wenzel Jakob's avatar
Wenzel Jakob committed
299
300
301
        return *this;
    }

302
    module def_submodule(const char *name, const char *doc = nullptr) {
Wenzel Jakob's avatar
Wenzel Jakob committed
303
304
305
        std::string full_name = std::string(PyModule_GetName(m_ptr))
            + std::string(".") + std::string(name);
        module result(PyImport_AddModule(full_name.c_str()), true);
306
307
        if (doc)
            result.attr("__doc__") = pybind::str(doc);
Wenzel Jakob's avatar
Wenzel Jakob committed
308
309
310
311
312
313
314
315
316
        attr(name) = result;
        return result;
    }
};

NAMESPACE_BEGIN(detail)
/// Basic support for creating new Python heap types
class custom_type : public object {
public:
Wenzel Jakob's avatar
Wenzel Jakob committed
317
    PYBIND_OBJECT_DEFAULT(custom_type, object, PyType_Check)
Wenzel Jakob's avatar
Wenzel Jakob committed
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365

    custom_type(object &scope, const char *name_, const std::string &type_name,
                size_t type_size, size_t instance_size,
                void (*init_holder)(PyObject *), const destructor &dealloc,
                PyObject *parent, const char *doc) {
        PyHeapTypeObject *type = (PyHeapTypeObject*) PyType_Type.tp_alloc(&PyType_Type, 0);
        PyObject *name = PyUnicode_FromString(name_);
        if (type == nullptr || name == nullptr)
            throw std::runtime_error("Internal error in custom_type::custom_type()");
        Py_INCREF(name);
        std::string full_name(name_);

        pybind::str scope_name = (object) scope.attr("__name__"),
                    module_name = (object) scope.attr("__module__");

        if (scope_name.check())
            full_name =  std::string(scope_name) + "." + full_name;
        if (module_name.check())
            full_name =  std::string(module_name) + "." + full_name;

        type->ht_name = type->ht_qualname = name;
        type->ht_type.tp_name = strdup(full_name.c_str());
        type->ht_type.tp_basicsize = instance_size;
        type->ht_type.tp_init = (initproc) init;
        type->ht_type.tp_new = (newfunc) new_instance;
        type->ht_type.tp_dealloc = dealloc;
        type->ht_type.tp_flags |=
            Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
        type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC;
        type->ht_type.tp_as_number = &type->as_number;
        type->ht_type.tp_as_sequence = &type->as_sequence;
        type->ht_type.tp_as_mapping = &type->as_mapping;
        type->ht_type.tp_base = (PyTypeObject *) parent;
        Py_XINCREF(parent);

        if (PyType_Ready(&type->ht_type) < 0)
            throw std::runtime_error("Internal error in custom_type::custom_type()");
        m_ptr = (PyObject *) type;

        /* Needed by pydoc */
        if (((module &) scope).check())
            attr("__module__") = scope_name;

        auto &type_info = detail::get_internals().registered_types[type_name];
        type_info.type = (PyTypeObject *) m_ptr;
        type_info.type_size = type_size;
        type_info.init_holder = init_holder;
        attr("__pybind__") = capsule(&type_info);
366
367
        if (doc)
            attr("__doc__") = pybind::str(doc);
Wenzel Jakob's avatar
Wenzel Jakob committed
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429

        scope.attr(name) = *this;
    }

protected:
    /* Allocate a metaclass on demand (for static properties) */
    handle metaclass() {
        auto &ht_type = ((PyHeapTypeObject *) m_ptr)->ht_type;
        auto &ob_type = ht_type.ob_base.ob_base.ob_type;
        if (ob_type == &PyType_Type) {
            std::string name_ = std::string(ht_type.tp_name) + "_meta";
            PyHeapTypeObject *type = (PyHeapTypeObject*) PyType_Type.tp_alloc(&PyType_Type, 0);
            PyObject *name = PyUnicode_FromString(name_.c_str());
            if (type == nullptr || name == nullptr)
                throw std::runtime_error("Internal error in custom_type::metaclass()");
            Py_INCREF(name);
            type->ht_name = type->ht_qualname = name;
            type->ht_type.tp_name = strdup(name_.c_str());
            type->ht_type.tp_base = &PyType_Type;
            type->ht_type.tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE;
            type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC;
            if (PyType_Ready(&type->ht_type) < 0)
                throw std::runtime_error("Internal error in custom_type::metaclass()");
            ob_type = (PyTypeObject *) type;
            Py_INCREF(type);
        }
        return handle((PyObject *) ob_type);
    }

    static int init(void *self, PyObject *, PyObject *) {
        std::string msg = std::string(Py_TYPE(self)->tp_name) + ": No constructor defined!";
        PyErr_SetString(PyExc_TypeError, msg.c_str());
        return -1;
    }

    static PyObject *new_instance(PyTypeObject *type, PyObject *, PyObject *) {
        const detail::type_info *type_info = capsule(
            PyObject_GetAttrString((PyObject *) type, const_cast<char*>("__pybind__")), false);
        instance<void> *self = (instance<void> *) PyType_GenericAlloc(type, 0);
        self->value = ::operator new(type_info->type_size);
        self->owned = true;
        self->parent = nullptr;
        self->constructed = false;
        detail::get_internals().registered_instances[self->value] = (PyObject *) self;
        return (PyObject *) self;
    }

    static void dealloc(instance<void> *self) {
        if (self->value) {
            bool dont_cache = self->parent && ((instance<void> *) self->parent)->value == self->value;
            if (!dont_cache) { // avoid an issue with internal references matching their parent's address
                auto &registered_instances = detail::get_internals().registered_instances;
                auto it = registered_instances.find(self->value);
                if (it == registered_instances.end())
                    throw std::runtime_error("Deallocating unregistered instance!");
                registered_instances.erase(it);
            }
            Py_XDECREF(self->parent);
        }
        Py_TYPE(self)->tp_free((PyObject*) self);
    }

Wenzel Jakob's avatar
Wenzel Jakob committed
430
431
432
    void install_buffer_funcs(
            buffer_info *(*get_buffer)(PyObject *, void *),
            void *get_buffer_data) {
Wenzel Jakob's avatar
Wenzel Jakob committed
433
434
435
436
        PyHeapTypeObject *type = (PyHeapTypeObject*) m_ptr;
        type->ht_type.tp_as_buffer = &type->as_buffer;
        type->as_buffer.bf_getbuffer = getbuffer;
        type->as_buffer.bf_releasebuffer = releasebuffer;
Wenzel Jakob's avatar
Wenzel Jakob committed
437
438
439
        auto info = ((detail::type_info *) capsule(attr("__pybind__")));
        info->get_buffer = get_buffer;
        info->get_buffer_data = get_buffer_data;
Wenzel Jakob's avatar
Wenzel Jakob committed
440
441
442
    }

    static int getbuffer(PyObject *obj, Py_buffer *view, int flags) {
Wenzel Jakob's avatar
Wenzel Jakob committed
443
444
445
        auto const &typeinfo = ((detail::type_info *) capsule(handle(obj).attr("__pybind__")));

        if (view == nullptr || obj == nullptr || !typeinfo || !typeinfo->get_buffer) {
Wenzel Jakob's avatar
Wenzel Jakob committed
446
447
448
449
            PyErr_SetString(PyExc_BufferError, "Internal error");
            return -1;
        }
        memset(view, 0, sizeof(Py_buffer));
Wenzel Jakob's avatar
Wenzel Jakob committed
450
        buffer_info *info = typeinfo->get_buffer(obj, typeinfo->get_buffer_data);
Wenzel Jakob's avatar
Wenzel Jakob committed
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
        view->obj = obj;
        view->ndim = 1;
        view->internal = info;
        view->buf = info->ptr;
        view->itemsize = info->itemsize;
        view->len = view->itemsize;
        for (auto s : info->shape)
            view->len *= s;
        if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT)
            view->format = const_cast<char *>(info->format.c_str());
        if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
            view->ndim = info->ndim;
            view->strides = (Py_ssize_t *)&info->strides[0];
            view->shape = (Py_ssize_t *) &info->shape[0];
        }
        Py_INCREF(view->obj);
        return 0;
    }

    static void releasebuffer(PyObject *, Py_buffer *view) { delete (buffer_info *) view->internal; }
};
472
473
474
475
476
477
478

/* Forward declarations */
enum op_id : int;
enum op_type : int;
struct undefined_t;
template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t> struct op_;
template <typename... Args> struct init;
Wenzel Jakob's avatar
Wenzel Jakob committed
479
480
481
482
483
484
NAMESPACE_END(detail)

template <typename type, typename holder_type = std::unique_ptr<type>> class class_ : public detail::custom_type {
public:
    typedef detail::instance<type, holder_type> instance_type;

Wenzel Jakob's avatar
Wenzel Jakob committed
485
    PYBIND_OBJECT(class_, detail::custom_type, PyType_Check)
Wenzel Jakob's avatar
Wenzel Jakob committed
486
487
488
489
490
491
492
493
494
495
496
497

    class_(object &scope, const char *name, const char *doc = nullptr)
        : detail::custom_type(scope, name, type_id<type>(), sizeof(type),
                              sizeof(instance_type), init_holder, dealloc,
                              nullptr, doc) { }

    class_(object &scope, const char *name, object &parent,
           const char *doc = nullptr)
        : detail::custom_type(scope, name, type_id<type>(), sizeof(type),
                              sizeof(instance_type), init_holder, dealloc,
                              parent.ptr(), doc) { }

498
499
500
501
502
    template <typename Func, typename... Extra>
    class_ &def(const char *name_, Func&& f, Extra&&... extra) {
        attr(name_) = cpp_function(std::forward<Func>(f), name(name_),
                                   sibling(attr(name_)), is_method(),
                                   std::forward<Extra>(extra)...);
Wenzel Jakob's avatar
Wenzel Jakob committed
503
504
505
        return *this;
    }

506
507
508
509
510
    template <typename Func, typename... Extra> class_ &
    def_static(const char *name_, Func f, Extra&&... extra) {
        attr(name_) = cpp_function(std::forward<Func>(f), name(name_),
                                   sibling(attr(name_)),
                                   std::forward<Extra>(extra)...);
Wenzel Jakob's avatar
Wenzel Jakob committed
511
512
513
        return *this;
    }

514
515
516
    template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
    class_ &def(const detail::op_<id, ot, L, R> &op, Extra&&... extra) {
        op.template execute<type>(*this, std::forward<Extra>(extra)...);
Wenzel Jakob's avatar
Wenzel Jakob committed
517
518
519
        return *this;
    }

520
521
522
    template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
    class_ & def_cast(const detail::op_<id, ot, L, R> &op, Extra&&... extra) {
        op.template execute_cast<type>(*this, std::forward<Extra>(extra)...);
Wenzel Jakob's avatar
Wenzel Jakob committed
523
524
525
        return *this;
    }

526
527
528
    template <typename... Args, typename... Extra>
    class_ &def(const detail::init<Args...> &init, Extra&&... extra) {
        init.template execute<type>(*this, std::forward<Extra>(extra)...);
Wenzel Jakob's avatar
Wenzel Jakob committed
529
530
531
        return *this;
    }

532
    template <typename Func> class_& def_buffer(Func &&func) {
Wenzel Jakob's avatar
Wenzel Jakob committed
533
534
535
        struct capture { Func func; };
        capture *ptr = new capture { std::forward<Func>(func) };
        install_buffer_funcs([](PyObject *obj, void *ptr) -> buffer_info* {
Wenzel Jakob's avatar
Wenzel Jakob committed
536
537
538
            detail::type_caster<type> caster;
            if (!caster.load(obj, false))
                return nullptr;
Wenzel Jakob's avatar
Wenzel Jakob committed
539
540
            return new buffer_info(((capture *) ptr)->func(caster));
        }, ptr);
Wenzel Jakob's avatar
Wenzel Jakob committed
541
542
543
        return *this;
    }

544
545
546
547
548
549
550
551
    template <typename C, typename D, typename... Extra>
    class_ &def_readwrite(const char *name, D C::*pm, Extra&&... extra) {
        cpp_function fget([pm](const C &c) -> const D &{ return c.*pm; },
                          return_value_policy::reference_internal,
                          is_method(), extra...),
                     fset([pm](C &c, const D &value) { c.*pm = value; },
                          is_method(), extra...);
        def_property(name, fget, fset);
Wenzel Jakob's avatar
Wenzel Jakob committed
552
553
554
        return *this;
    }

555
556
557
558
559
560
    template <typename C, typename D, typename... Extra>
    class_ &def_readonly(const char *name, const D C::*pm, Extra&& ...extra) {
        cpp_function fget([pm](const C &c) -> const D &{ return c.*pm; },
                          return_value_policy::reference_internal,
                          is_method(), std::forward<Extra>(extra)...);
        def_property_readonly(name, fget);
Wenzel Jakob's avatar
Wenzel Jakob committed
561
562
563
        return *this;
    }

564
565
    template <typename D, typename... Extra>
    class_ &def_readwrite_static(const char *name, D *pm, Extra&& ...extra) {
566
        cpp_function fget([pm](object) -> const D &{ return *pm; }, nullptr,
567
568
569
                          return_value_policy::reference_internal, extra...),
                     fset([pm](object, const D &value) { *pm = value; }, extra...);
        def_property_static(name, fget, fset);
Wenzel Jakob's avatar
Wenzel Jakob committed
570
571
572
        return *this;
    }

573
574
    template <typename D, typename... Extra>
    class_ &def_readonly_static(const char *name, const D *pm, Extra&& ...extra) {
575
        cpp_function fget([pm](object) -> const D &{ return *pm; }, nullptr,
576
577
                          return_value_policy::reference_internal, std::forward<Extra>(extra)...);
        def_property_readonly_static(name, fget);
Wenzel Jakob's avatar
Wenzel Jakob committed
578
579
580
        return *this;
    }

581
582
    class_ &def_property_readonly(const char *name, const cpp_function &fget) {
        def_property(name, fget, cpp_function());
Wenzel Jakob's avatar
Wenzel Jakob committed
583
584
585
        return *this;
    }

586
587
    class_ &def_property_readonly_static(const char *name, const cpp_function &fget) {
        def_property_static(name, fget, cpp_function());
Wenzel Jakob's avatar
Wenzel Jakob committed
588
589
590
        return *this;
    }

591
    class_ &def_property(const char *name, const cpp_function &fget, const cpp_function &fset) {
Wenzel Jakob's avatar
Wenzel Jakob committed
592
593
        object property(
            PyObject_CallFunction((PyObject *)&PyProperty_Type,
594
595
596
                                  const_cast<char *>("OOOO"), fget.ptr() ? fget.ptr() : Py_None,
                                  fset.ptr() ? fset.ptr() : Py_None, Py_None,
                                  ((object) const_cast<cpp_function&>(fget).attr("__doc__")).ptr()), false);
Wenzel Jakob's avatar
Wenzel Jakob committed
597
598
599
600
        attr(name) = property;
        return *this;
    }

601
    class_ &def_property_static(const char *name, const cpp_function &fget, const cpp_function &fset) {
Wenzel Jakob's avatar
Wenzel Jakob committed
602
603
        object property(
            PyObject_CallFunction((PyObject *)&PyProperty_Type,
604
605
606
                                  const_cast<char *>("OOOO"), fget.ptr() ? fget.ptr() : Py_None,
                                  fset.ptr() ? fset.ptr() : Py_None, Py_None,
                                  ((object) const_cast<cpp_function&>(fget).attr("__doc__")).ptr()), false);
Wenzel Jakob's avatar
Wenzel Jakob committed
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
        metaclass().attr(name) = property;
        return *this;
    }
private:
    static void init_holder(PyObject *inst_) {
        instance_type *inst = (instance_type *) inst_;
        new (&inst->holder) holder_type(inst->value);
        inst->constructed = true;
    }
    static void dealloc(PyObject *inst_) {
        instance_type *inst = (instance_type *) inst_;
        if (inst->owned) {
            if (inst->constructed)
                inst->holder.~holder_type();
            else
                ::operator delete(inst->value);
        }
        custom_type::dealloc((detail::instance<void> *) inst);
    }
};

/// Binds C++ enumerations and enumeration classes to Python
template <typename Type> class enum_ : public class_<Type> {
public:
    enum_(object &scope, const char *name, const char *doc = nullptr)
      : class_<Type>(scope, name, doc), m_parent(scope) {
        auto entries = new std::unordered_map<int, const char *>();
        this->def("__str__", [name, entries](Type value) -> std::string {
            auto it = entries->find(value);
            return std::string(name) + "." +
                ((it == entries->end()) ? std::string("???")
                                        : std::string(it->second));
        });
        m_entries = entries;
    }

    /// Export enumeration entries into the parent scope
    void export_values() {
        PyObject *dict = ((PyTypeObject *) this->m_ptr)->tp_dict;
        PyObject *key, *value;
        Py_ssize_t pos = 0;
        while (PyDict_Next(dict, &pos, &key, &value))
            if (PyObject_IsInstance(value, this->m_ptr))
                m_parent.attr(key) = value;
    }

    /// Add an enumeration entry
    enum_& value(char const* name, Type value) {
        this->attr(name) = pybind::cast(value, return_value_policy::copy);
        (*m_entries)[(int) value] = name;
        return *this;
    }
private:
    std::unordered_map<int, const char *> *m_entries;
    object &m_parent;
};

NAMESPACE_BEGIN(detail)
665
666
template <typename... Args> struct init {
    template <typename Base, typename Holder, typename... Extra> void execute(pybind::class_<Base, Holder> &class_, Extra&&... extra) const {
Wenzel Jakob's avatar
Wenzel Jakob committed
667
        /// Function which calls a specific C++ in-place constructor
668
        class_.def("__init__", [](Base *instance, Args... args) { new (instance) Base(args...); }, std::forward<Extra>(extra)...);
Wenzel Jakob's avatar
Wenzel Jakob committed
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
    }
};
NAMESPACE_END(detail)

template <typename... Args> detail::init<Args...> init() { return detail::init<Args...>(); };

template <typename InputType, typename OutputType> void implicitly_convertible() {
    auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject *{
        if (!detail::type_caster<InputType>().load(obj, false))
            return nullptr;
        tuple args(1);
        args[0] = obj;
        PyObject *result = PyObject_Call((PyObject *) type, args.ptr(), nullptr);
        if (result == nullptr)
            PyErr_Clear();
        return result;
    };
    std::string output_type_name = type_id<OutputType>();
    auto & registered_types = detail::get_internals().registered_types;
    auto it = registered_types.find(output_type_name);
    if (it == registered_types.end())
        throw std::runtime_error("implicitly_convertible: Unable to find type " + output_type_name);
    it->second.implicit_conversions.push_back(implicit_caster);
}

inline void init_threading() { PyEval_InitThreads(); }

class gil_scoped_acquire {
    PyGILState_STATE state;
public:
    inline gil_scoped_acquire() { state = PyGILState_Ensure(); }
    inline ~gil_scoped_acquire() { PyGILState_Release(state); }
};

class gil_scoped_release {
    PyThreadState *state;
public:
    inline gil_scoped_release() { state = PyEval_SaveThread(); }
    inline ~gil_scoped_release() { PyEval_RestoreThread(state); }
};

NAMESPACE_END(pybind)

#if defined(_MSC_VER)
#pragma warning(pop)
#endif