blob: 9f285616ea8a0e760c47b002bcf72c74a0ff0ada [file] [log] [blame]
Wenzel Jakob38bd7112015-07-05 20:05:44 +02001/*
2 pybind/pybind.h: Main header file of the C++11 python binding generator library
3
4 Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
5
6 All rights reserved. Use of this source code is governed by a
7 BSD-style license that can be found in the LICENSE file.
8*/
9
Wenzel Jakobbd4a5292015-07-11 17:41:48 +020010#pragma once
Wenzel Jakob38bd7112015-07-05 20:05:44 +020011
12#if defined(_MSC_VER)
13#pragma warning(push)
14#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
15#pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning)
16#pragma warning(disable: 4996) // warning C4996: The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name
17#pragma warning(disable: 4100) // warning C4100: Unreferenced formal parameter
18#pragma warning(disable: 4512) // warning C4512: Assignment operator was implicitly defined as deleted
19#endif
20
Wenzel Jakobbd4a5292015-07-11 17:41:48 +020021#include <pybind/cast.h>
Wenzel Jakob38bd7112015-07-05 20:05:44 +020022
23NAMESPACE_BEGIN(pybind)
24
Wenzel Jakobbd4a5292015-07-11 17:41:48 +020025class cpp_function : public function {
26public:
Wenzel Jakob38bd7112015-07-05 20:05:44 +020027 struct function_entry {
28 std::function<PyObject* (PyObject *)> impl;
29 std::string signature, doc;
30 bool is_constructor;
31 function_entry *next = nullptr;
32 };
Wenzel Jakob38bd7112015-07-05 20:05:44 +020033
Wenzel Jakobbd4a5292015-07-11 17:41:48 +020034 cpp_function() { }
35 template <typename Func> cpp_function(
36 Func &&_func, const char *name = nullptr, const char *doc = nullptr,
37 return_value_policy policy = return_value_policy::automatic,
38 function sibling = function(), bool is_method = false) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +020039 /* Function traits extracted from the template type 'Func' */
40 typedef mpl::function_traits<Func> f_traits;
41
42 /* Suitable input and output casters */
43 typedef typename detail::type_caster<typename f_traits::args_type> cast_in;
44 typedef typename detail::type_caster<typename mpl::normalize_type<typename f_traits::return_type>::type> cast_out;
Wenzel Jakobbd4a5292015-07-11 17:41:48 +020045 typename f_traits::f_type func = f_traits::cast(std::forward<Func>(_func));
Wenzel Jakob38bd7112015-07-05 20:05:44 +020046
47 auto impl = [func, policy](PyObject *pyArgs) -> PyObject *{
48 cast_in args;
49 if (!args.load(pyArgs, true))
50 return nullptr;
51 PyObject *parent = policy != return_value_policy::reference_internal
52 ? nullptr : PyTuple_GetItem(pyArgs, 0);
53 return cast_out::cast(
Wenzel Jakobbd4a5292015-07-11 17:41:48 +020054 f_traits::dispatch(func, args.operator typename f_traits::args_type()),
Wenzel Jakob38bd7112015-07-05 20:05:44 +020055 policy, parent);
56 };
57
Wenzel Jakobbd4a5292015-07-11 17:41:48 +020058 initialize(name, doc, cast_in::name() + std::string(" -> ") + cast_out::name(),
59 sibling, is_method, std::move(impl));
Wenzel Jakob38bd7112015-07-05 20:05:44 +020060 }
Wenzel Jakob38bd7112015-07-05 20:05:44 +020061private:
62 static PyObject *dispatcher(PyObject *self, PyObject *args, PyObject * /* kwargs */) {
63 function_entry *overloads = (function_entry *) PyCapsule_GetPointer(self, nullptr);
64 PyObject *result = nullptr;
65 try {
66 for (function_entry *it = overloads; it != nullptr; it = it->next) {
67 if ((result = it->impl(args)) != nullptr)
68 break;
69 }
70 } catch (const error_already_set &) { return nullptr;
71 } catch (const index_error &e) { PyErr_SetString(PyExc_IndexError, e.what()); return nullptr;
72 } catch (const stop_iteration &e) { PyErr_SetString(PyExc_StopIteration, e.what()); return nullptr;
73 } catch (const std::exception &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); return nullptr;
74 } catch (...) {
75 PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!");
76 return nullptr;
77 }
78 if (result) {
79 if (overloads->is_constructor) {
80 PyObject *inst = PyTuple_GetItem(args, 0);
81 const detail::type_info *type_info =
82 capsule(PyObject_GetAttrString((PyObject *) Py_TYPE(inst),
83 const_cast<char *>("__pybind__")), false);
84 type_info->init_holder(inst);
85 }
86 return result;
87 } else {
88 std::string signatures = "Incompatible function arguments. The "
89 "following argument types are supported:\n";
90 int ctr = 0;
91 for (function_entry *it = overloads; it != nullptr; it = it->next) {
92 signatures += " "+ std::to_string(++ctr) + ". ";
93 signatures += it->signature;
94 signatures += "\n";
95 }
96 PyErr_SetString(PyExc_TypeError, signatures.c_str());
97 return nullptr;
98 }
99 }
100
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200101 void initialize(const char *name, const char *doc,
102 const std::string &signature, function sibling,
103 bool is_method, std::function<PyObject *(PyObject *)> &&impl) {
104 if (name == nullptr)
105 name = "";
106
107 /* Linked list of function call handlers (for overloading) */
108 function_entry *entry = new function_entry();
109 entry->impl = std::move(impl);
110 entry->is_constructor = !strcmp(name, "__init__");
111 entry->signature = signature;
112 if (doc) entry->doc = doc;
113
114 if (!sibling.ptr() || !PyCFunction_Check(sibling.ptr())) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200115 PyMethodDef *def = new PyMethodDef();
116 memset(def, 0, sizeof(PyMethodDef));
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200117 def->ml_name = name != nullptr ? strdup(name) : name;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200118 def->ml_meth = reinterpret_cast<PyCFunction>(*dispatcher);
119 def->ml_flags = METH_VARARGS | METH_KEYWORDS;
120 capsule entry_capsule(entry);
121 m_ptr = PyCFunction_New(def, entry_capsule.ptr());
122 if (!m_ptr)
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200123 throw std::runtime_error("cpp_function::cpp_function(): Could not allocate function object");
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200124 } else {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200125 m_ptr = sibling.ptr();
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200126 inc_ref();
127 capsule entry_capsule(PyCFunction_GetSelf(m_ptr), true);
128 function_entry *parent = (function_entry *) entry_capsule, *backup = parent;
129 while (parent->next)
130 parent = parent->next;
131 parent->next = entry;
132 entry = backup;
133 }
134 std::string signatures;
135 while (entry) { /* Create pydoc entry */
136 signatures += "Signature : " + std::string(entry->signature) + "\n";
137 if (!entry->doc.empty())
138 signatures += "\n" + std::string(entry->doc) + "\n";
139 if (entry->next)
140 signatures += "\n";
141 entry = entry->next;
142 }
143 PyCFunctionObject *func = (PyCFunctionObject *) m_ptr;
144 if (func->m_ml->ml_doc)
145 std::free((char *) func->m_ml->ml_doc);
146 func->m_ml->ml_doc = strdup(signatures.c_str());
147 if (is_method) {
148 m_ptr = PyInstanceMethod_New(m_ptr);
149 if (!m_ptr)
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200150 throw std::runtime_error("cpp_function::cpp_function(): Could not allocate instance method object");
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200151 Py_DECREF(func);
152 }
153 }
154};
155
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200156class cpp_method : public cpp_function {
157public:
158 cpp_method () { }
159 template <typename Func>
160 cpp_method(Func &&_func, const char *name = nullptr, const char *doc = nullptr,
161 return_value_policy policy = return_value_policy::automatic,
162 function sibling = function())
163 : cpp_function(std::forward<Func>(_func), name, doc, policy, sibling, true) { }
164};
165
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200166class module : public object {
167public:
168 PYTHON_OBJECT_DEFAULT(module, object, PyModule_Check)
169
170 module(const char *name, const char *doc = nullptr) {
171 PyModuleDef *def = new PyModuleDef();
172 memset(def, 0, sizeof(PyModuleDef));
173 def->m_name = name;
174 def->m_doc = doc;
175 def->m_size = -1;
176 Py_INCREF(def);
177 m_ptr = PyModule_Create(def);
178 if (m_ptr == nullptr)
179 throw std::runtime_error("Internal error in module::module()");
180 inc_ref();
181 }
182
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200183 template <typename Func>
184 module &def(const char *name, Func f, const char *doc = nullptr,
185 return_value_policy policy = return_value_policy::automatic) {
186 cpp_function func(f, name, doc, policy, (function) attr(name));
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200187 func.inc_ref(); /* The following line steals a reference to 'func' */
188 PyModule_AddObject(ptr(), name, func.ptr());
189 return *this;
190 }
191
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200192 module def_submodule(const char *name, const char *doc = nullptr) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200193 std::string full_name = std::string(PyModule_GetName(m_ptr))
194 + std::string(".") + std::string(name);
195 module result(PyImport_AddModule(full_name.c_str()), true);
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200196 if (doc)
197 result.attr("__doc__") = pybind::str(doc);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200198 attr(name) = result;
199 return result;
200 }
201};
202
203NAMESPACE_BEGIN(detail)
204/* Forward declarations */
205enum op_id : int;
206enum op_type : int;
207struct undefined_t;
208template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t> struct op_;
209template <typename ... Args> struct init;
210
211/// Basic support for creating new Python heap types
212class custom_type : public object {
213public:
214 PYTHON_OBJECT_DEFAULT(custom_type, object, PyType_Check)
215
216 custom_type(object &scope, const char *name_, const std::string &type_name,
217 size_t type_size, size_t instance_size,
218 void (*init_holder)(PyObject *), const destructor &dealloc,
219 PyObject *parent, const char *doc) {
220 PyHeapTypeObject *type = (PyHeapTypeObject*) PyType_Type.tp_alloc(&PyType_Type, 0);
221 PyObject *name = PyUnicode_FromString(name_);
222 if (type == nullptr || name == nullptr)
223 throw std::runtime_error("Internal error in custom_type::custom_type()");
224 Py_INCREF(name);
225 std::string full_name(name_);
226
227 pybind::str scope_name = (object) scope.attr("__name__"),
228 module_name = (object) scope.attr("__module__");
229
230 if (scope_name.check())
231 full_name = std::string(scope_name) + "." + full_name;
232 if (module_name.check())
233 full_name = std::string(module_name) + "." + full_name;
234
235 type->ht_name = type->ht_qualname = name;
236 type->ht_type.tp_name = strdup(full_name.c_str());
237 type->ht_type.tp_basicsize = instance_size;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200238 type->ht_type.tp_init = (initproc) init;
239 type->ht_type.tp_new = (newfunc) new_instance;
240 type->ht_type.tp_dealloc = dealloc;
241 type->ht_type.tp_flags |=
242 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
243 type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC;
244 type->ht_type.tp_as_number = &type->as_number;
245 type->ht_type.tp_as_sequence = &type->as_sequence;
246 type->ht_type.tp_as_mapping = &type->as_mapping;
247 type->ht_type.tp_base = (PyTypeObject *) parent;
248 Py_XINCREF(parent);
249
250 if (PyType_Ready(&type->ht_type) < 0)
251 throw std::runtime_error("Internal error in custom_type::custom_type()");
252 m_ptr = (PyObject *) type;
253
254 /* Needed by pydoc */
255 if (((module &) scope).check())
256 attr("__module__") = scope_name;
257
258 auto &type_info = detail::get_internals().registered_types[type_name];
259 type_info.type = (PyTypeObject *) m_ptr;
260 type_info.type_size = type_size;
261 type_info.init_holder = init_holder;
262 attr("__pybind__") = capsule(&type_info);
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200263 if (doc)
264 attr("__doc__") = pybind::str(doc);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200265
266 scope.attr(name) = *this;
267 }
268
269protected:
270 /* Allocate a metaclass on demand (for static properties) */
271 handle metaclass() {
272 auto &ht_type = ((PyHeapTypeObject *) m_ptr)->ht_type;
273 auto &ob_type = ht_type.ob_base.ob_base.ob_type;
274 if (ob_type == &PyType_Type) {
275 std::string name_ = std::string(ht_type.tp_name) + "_meta";
276 PyHeapTypeObject *type = (PyHeapTypeObject*) PyType_Type.tp_alloc(&PyType_Type, 0);
277 PyObject *name = PyUnicode_FromString(name_.c_str());
278 if (type == nullptr || name == nullptr)
279 throw std::runtime_error("Internal error in custom_type::metaclass()");
280 Py_INCREF(name);
281 type->ht_name = type->ht_qualname = name;
282 type->ht_type.tp_name = strdup(name_.c_str());
283 type->ht_type.tp_base = &PyType_Type;
284 type->ht_type.tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE;
285 type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC;
286 if (PyType_Ready(&type->ht_type) < 0)
287 throw std::runtime_error("Internal error in custom_type::metaclass()");
288 ob_type = (PyTypeObject *) type;
289 Py_INCREF(type);
290 }
291 return handle((PyObject *) ob_type);
292 }
293
294 static int init(void *self, PyObject *, PyObject *) {
295 std::string msg = std::string(Py_TYPE(self)->tp_name) + ": No constructor defined!";
296 PyErr_SetString(PyExc_TypeError, msg.c_str());
297 return -1;
298 }
299
300 static PyObject *new_instance(PyTypeObject *type, PyObject *, PyObject *) {
301 const detail::type_info *type_info = capsule(
302 PyObject_GetAttrString((PyObject *) type, const_cast<char*>("__pybind__")), false);
303 instance<void> *self = (instance<void> *) PyType_GenericAlloc(type, 0);
304 self->value = ::operator new(type_info->type_size);
305 self->owned = true;
306 self->parent = nullptr;
307 self->constructed = false;
308 detail::get_internals().registered_instances[self->value] = (PyObject *) self;
309 return (PyObject *) self;
310 }
311
312 static void dealloc(instance<void> *self) {
313 if (self->value) {
314 bool dont_cache = self->parent && ((instance<void> *) self->parent)->value == self->value;
315 if (!dont_cache) { // avoid an issue with internal references matching their parent's address
316 auto &registered_instances = detail::get_internals().registered_instances;
317 auto it = registered_instances.find(self->value);
318 if (it == registered_instances.end())
319 throw std::runtime_error("Deallocating unregistered instance!");
320 registered_instances.erase(it);
321 }
322 Py_XDECREF(self->parent);
323 }
324 Py_TYPE(self)->tp_free((PyObject*) self);
325 }
326
327 void install_buffer_funcs(const std::function<buffer_info *(PyObject *)> &func) {
328 PyHeapTypeObject *type = (PyHeapTypeObject*) m_ptr;
329 type->ht_type.tp_as_buffer = &type->as_buffer;
330 type->as_buffer.bf_getbuffer = getbuffer;
331 type->as_buffer.bf_releasebuffer = releasebuffer;
332 ((detail::type_info *) capsule(attr("__pybind__")))->get_buffer = func;
333 }
334
335 static int getbuffer(PyObject *obj, Py_buffer *view, int flags) {
336 auto const &info_func = ((detail::type_info *) capsule(handle(obj).attr("__pybind__")))->get_buffer;
337 if (view == nullptr || obj == nullptr || !info_func) {
338 PyErr_SetString(PyExc_BufferError, "Internal error");
339 return -1;
340 }
341 memset(view, 0, sizeof(Py_buffer));
342 buffer_info *info = info_func(obj);
343 view->obj = obj;
344 view->ndim = 1;
345 view->internal = info;
346 view->buf = info->ptr;
347 view->itemsize = info->itemsize;
348 view->len = view->itemsize;
349 for (auto s : info->shape)
350 view->len *= s;
351 if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT)
352 view->format = const_cast<char *>(info->format.c_str());
353 if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
354 view->ndim = info->ndim;
355 view->strides = (Py_ssize_t *)&info->strides[0];
356 view->shape = (Py_ssize_t *) &info->shape[0];
357 }
358 Py_INCREF(view->obj);
359 return 0;
360 }
361
362 static void releasebuffer(PyObject *, Py_buffer *view) { delete (buffer_info *) view->internal; }
363};
364
365NAMESPACE_END(detail)
366
367template <typename type, typename holder_type = std::unique_ptr<type>> class class_ : public detail::custom_type {
368public:
369 typedef detail::instance<type, holder_type> instance_type;
370
371 PYTHON_OBJECT(class_, detail::custom_type, PyType_Check)
372
373 class_(object &scope, const char *name, const char *doc = nullptr)
374 : detail::custom_type(scope, name, type_id<type>(), sizeof(type),
375 sizeof(instance_type), init_holder, dealloc,
376 nullptr, doc) { }
377
378 class_(object &scope, const char *name, object &parent,
379 const char *doc = nullptr)
380 : detail::custom_type(scope, name, type_id<type>(), sizeof(type),
381 sizeof(instance_type), init_holder, dealloc,
382 parent.ptr(), doc) { }
383
384 template <typename Func>
385 class_ &def(const char *name, Func f, const char *doc = nullptr,
386 return_value_policy policy = return_value_policy::automatic) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200387 attr(name) = cpp_method(f, name, doc, policy, (function) attr(name));
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200388 return *this;
389 }
390
391 template <typename Func> class_ &
392 def_static(const char *name, Func f, const char *doc = nullptr,
393 return_value_policy policy = return_value_policy::automatic) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200394 attr(name) = cpp_function(f, name, doc, policy, (function) attr(name));
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200395 return *this;
396 }
397
398 template <detail::op_id id, detail::op_type ot, typename L, typename R>
399 class_ &def(const detail::op_<id, ot, L, R> &op, const char *doc = nullptr,
400 return_value_policy policy = return_value_policy::automatic) {
401 op.template execute<type>(*this, doc, policy);
402 return *this;
403 }
404
405 template <detail::op_id id, detail::op_type ot, typename L, typename R> class_ &
406 def_cast(const detail::op_<id, ot, L, R> &op, const char *doc = nullptr,
407 return_value_policy policy = return_value_policy::automatic) {
408 op.template execute_cast<type>(*this, doc, policy);
409 return *this;
410 }
411
412 template <typename... Args>
413 class_ &def(const detail::init<Args...> &init, const char *doc = nullptr) {
414 init.template execute<type>(*this, doc);
415 return *this;
416 }
417
418 class_& def_buffer(const std::function<buffer_info(type&)> &func) {
419 install_buffer_funcs([func](PyObject *obj) -> buffer_info* {
420 detail::type_caster<type> caster;
421 if (!caster.load(obj, false))
422 return nullptr;
423 return new buffer_info(func(caster));
424 });
425 return *this;
426 }
427
428 template <typename C, typename D>
429 class_ &def_readwrite(const char *name, D C::*pm,
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200430 const char *doc = nullptr) {
431 cpp_method fget([pm](const C &c) -> const D &{ return c.*pm; }, nullptr,
432 nullptr, return_value_policy::reference_internal),
433 fset([pm](C &c, const D &value) { c.*pm = value; });
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200434 def_property(name, fget, fset, doc);
435 return *this;
436 }
437
438 template <typename C, typename D>
439 class_ &def_readonly(const char *name, const D C::*pm,
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200440 const char *doc = nullptr) {
441 cpp_method fget([pm](const C &c) -> const D &{ return c.*pm; }, nullptr,
442 nullptr, return_value_policy::reference_internal);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200443 def_property(name, fget, doc);
444 return *this;
445 }
446
447 template <typename D>
448 class_ &def_readwrite_static(const char *name, D *pm,
449 const char *doc = nullptr) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200450 cpp_function fget([pm](object) -> const D &{ return *pm; }, nullptr,
451 nullptr, return_value_policy::reference_internal),
452 fset([pm](object, const D &value) { *pm = value; });
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200453 def_property_static(name, fget, fset, doc);
454 return *this;
455 }
456
457 template <typename D>
458 class_ &def_readonly_static(const char *name, const D *pm,
459 const char *doc = nullptr) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200460 cpp_function fget([pm](object) -> const D &{ return *pm; }, nullptr,
461 nullptr, return_value_policy::reference_internal);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200462 def_property_static(name, fget, doc);
463 return *this;
464 }
465
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200466 class_ &def_property(const char *name, const cpp_method &fget,
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200467 const char *doc = nullptr) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200468 def_property(name, fget, cpp_method(), doc);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200469 return *this;
470 }
471
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200472 class_ &def_property_static(const char *name, const cpp_function &fget,
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200473 const char *doc = nullptr) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200474 def_property_static(name, fget, cpp_function(), doc);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200475 return *this;
476 }
477
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200478 class_ &def_property(const char *name, const cpp_method &fget,
479 const cpp_method &fset, const char *doc = nullptr) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200480 object property(
481 PyObject_CallFunction((PyObject *)&PyProperty_Type,
482 const_cast<char *>("OOOs"), fget.ptr() ? fget.ptr() : Py_None,
483 fset.ptr() ? fset.ptr() : Py_None, Py_None, doc), false);
484 attr(name) = property;
485 return *this;
486 }
487
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200488 class_ &def_property_static(const char *name, const cpp_function &fget,
489 const cpp_function &fset,
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200490 const char *doc = nullptr) {
491 object property(
492 PyObject_CallFunction((PyObject *)&PyProperty_Type,
493 const_cast<char *>("OOOs"), fget.ptr() ? fget.ptr() : Py_None,
494 fset.ptr() ? fset.ptr() : Py_None, Py_None, doc), false);
495 metaclass().attr(name) = property;
496 return *this;
497 }
498private:
499 static void init_holder(PyObject *inst_) {
500 instance_type *inst = (instance_type *) inst_;
501 new (&inst->holder) holder_type(inst->value);
502 inst->constructed = true;
503 }
504 static void dealloc(PyObject *inst_) {
505 instance_type *inst = (instance_type *) inst_;
506 if (inst->owned) {
507 if (inst->constructed)
508 inst->holder.~holder_type();
509 else
510 ::operator delete(inst->value);
511 }
512 custom_type::dealloc((detail::instance<void> *) inst);
513 }
514};
515
516/// Binds C++ enumerations and enumeration classes to Python
517template <typename Type> class enum_ : public class_<Type> {
518public:
519 enum_(object &scope, const char *name, const char *doc = nullptr)
520 : class_<Type>(scope, name, doc), m_parent(scope) {
521 auto entries = new std::unordered_map<int, const char *>();
522 this->def("__str__", [name, entries](Type value) -> std::string {
523 auto it = entries->find(value);
524 return std::string(name) + "." +
525 ((it == entries->end()) ? std::string("???")
526 : std::string(it->second));
527 });
528 m_entries = entries;
529 }
530
531 /// Export enumeration entries into the parent scope
532 void export_values() {
533 PyObject *dict = ((PyTypeObject *) this->m_ptr)->tp_dict;
534 PyObject *key, *value;
535 Py_ssize_t pos = 0;
536 while (PyDict_Next(dict, &pos, &key, &value))
537 if (PyObject_IsInstance(value, this->m_ptr))
538 m_parent.attr(key) = value;
539 }
540
541 /// Add an enumeration entry
542 enum_& value(char const* name, Type value) {
543 this->attr(name) = pybind::cast(value, return_value_policy::copy);
544 (*m_entries)[(int) value] = name;
545 return *this;
546 }
547private:
548 std::unordered_map<int, const char *> *m_entries;
549 object &m_parent;
550};
551
552NAMESPACE_BEGIN(detail)
553template <typename ... Args> struct init {
554 template <typename Base, typename Holder> void execute(pybind::class_<Base, Holder> &class_, const char *doc) const {
555 /// Function which calls a specific C++ in-place constructor
556 class_.def("__init__", [](Base *instance, Args... args) { new (instance) Base(args...); }, doc);
557 }
558};
559NAMESPACE_END(detail)
560
561template <typename... Args> detail::init<Args...> init() { return detail::init<Args...>(); };
562
563template <typename InputType, typename OutputType> void implicitly_convertible() {
564 auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject *{
565 if (!detail::type_caster<InputType>().load(obj, false))
566 return nullptr;
567 tuple args(1);
568 args[0] = obj;
569 PyObject *result = PyObject_Call((PyObject *) type, args.ptr(), nullptr);
570 if (result == nullptr)
571 PyErr_Clear();
572 return result;
573 };
574 std::string output_type_name = type_id<OutputType>();
575 auto & registered_types = detail::get_internals().registered_types;
576 auto it = registered_types.find(output_type_name);
577 if (it == registered_types.end())
578 throw std::runtime_error("implicitly_convertible: Unable to find type " + output_type_name);
579 it->second.implicit_conversions.push_back(implicit_caster);
580}
581
582inline void init_threading() { PyEval_InitThreads(); }
583
584class gil_scoped_acquire {
585 PyGILState_STATE state;
586public:
587 inline gil_scoped_acquire() { state = PyGILState_Ensure(); }
588 inline ~gil_scoped_acquire() { PyGILState_Release(state); }
589};
590
591class gil_scoped_release {
592 PyThreadState *state;
593public:
594 inline gil_scoped_release() { state = PyEval_SaveThread(); }
595 inline ~gil_scoped_release() { PyEval_RestoreThread(state); }
596};
597
598NAMESPACE_END(pybind)
599
600#if defined(_MSC_VER)
601#pragma warning(pop)
602#endif
603
604#undef PYTHON_OBJECT
605#undef PYTHON_OBJECT_DEFAULT