blob: e8c4ff5d79c28ef1a2aade29b0f7ff775e35b812 [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 Jakobd4258ba2015-07-26 16:33:49 +020025/// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object
Wenzel Jakobbd4a5292015-07-11 17:41:48 +020026class cpp_function : public function {
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020027private:
28 /// Chained list of function entries for overloading
Wenzel Jakob38bd7112015-07-05 20:05:44 +020029 struct function_entry {
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020030 PyObject * (*impl) (function_entry *, PyObject *, PyObject *);
31 void *data;
Wenzel Jakob38bd7112015-07-05 20:05:44 +020032 std::string signature, doc;
33 bool is_constructor;
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020034 return_value_policy policy;
Wenzel Jakob38bd7112015-07-05 20:05:44 +020035 function_entry *next = nullptr;
36 };
Wenzel Jakob38bd7112015-07-05 20:05:44 +020037
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020038 /// Picks a suitable return value converter from cast.h
39 template <typename T> using return_value_caster =
40 detail::type_caster<typename std::conditional<
41 std::is_void<T>::value, detail::void_type, typename detail::decay<T>::type>::type>;
42
43 /// Picks a suitable argument value converter from cast.h
44 template <typename ... T> using arg_value_caster =
45 detail::type_caster<typename std::tuple<T...>>;
46public:
Wenzel Jakobbd4a5292015-07-11 17:41:48 +020047 cpp_function() { }
Wenzel Jakob38bd7112015-07-05 20:05:44 +020048
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020049 /// Vanilla function pointers
50 template <typename return_type, typename... arg_type>
51 cpp_function(return_type (*f)(arg_type...), const char *name = nullptr,
52 const char *doc = nullptr, return_value_policy policy = return_value_policy::automatic,
53 const function &sibling = function(), bool is_method = false) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +020054
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020055 typedef arg_value_caster<arg_type...> cast_in;
56 typedef return_value_caster<return_type> cast_out;
57
58 auto impl = [](function_entry *entry, PyObject *pyArgs, PyObject *parent) -> PyObject * {
Wenzel Jakob38bd7112015-07-05 20:05:44 +020059 cast_in args;
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020060 if (!args.load(pyArgs, true)) return nullptr;
61 auto f = (return_type (*) (arg_type...)) entry->data;
62 return cast_out::cast(args.template call<return_type>(f),
63 entry->policy, parent);
Wenzel Jakob38bd7112015-07-05 20:05:44 +020064 };
65
Wenzel Jakobbd4a5292015-07-11 17:41:48 +020066 initialize(name, doc, cast_in::name() + std::string(" -> ") + cast_out::name(),
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020067 sibling, is_method, policy, impl, (void *) f);
Wenzel Jakob38bd7112015-07-05 20:05:44 +020068 }
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020069
70 /// Delegating helper constructor to deal with lambda functions
71 template <typename func>
72 cpp_function(func &&f, const char *name = nullptr,
73 const char *doc = nullptr,
74 return_value_policy policy = return_value_policy::automatic,
75 const function &sibling = function(), bool is_method = false) {
76 initialize(std::forward<func>(f), name, doc, policy, sibling, is_method,
77 (typename detail::remove_class<decltype(
78 &std::remove_reference<func>::type::operator())>::type *) nullptr);
79 }
80
81
82 /// Class methods (non-const)
83 template <typename return_type, typename class_type, typename ... arg_type> cpp_function(
84 return_type (class_type::*f)(arg_type...), const char *name = nullptr,
85 const char *doc = nullptr, return_value_policy policy = return_value_policy::automatic,
86 const function &sibling = function(), bool is_method = false) {
87 initialize([f](class_type *c, arg_type... args) -> return_type { return (c->*f)(args...); },
88 name, doc, policy, sibling, is_method, (return_type (*)(class_type *, arg_type ...)) nullptr);
89 }
90
91 /// Class methods (const)
92 template <typename return_type, typename class_type, typename ... arg_type> cpp_function(
93 return_type (class_type::*f)(arg_type...) const, const char *name = nullptr,
94 const char *doc = nullptr, return_value_policy policy = return_value_policy::automatic,
95 const function &sibling = function(), bool is_method = false) {
96 initialize([f](const class_type *c, arg_type... args) -> return_type { return (c->*f)(args...); },
97 name, doc, policy, sibling, is_method, (return_type (*)(const class_type *, arg_type ...)) nullptr);
98 }
99
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200100private:
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200101 /// Functors, lambda functions, etc.
102 template <typename func, typename return_type, typename... arg_type>
103 void initialize(func &&f, const char *name, const char *doc,
104 return_value_policy policy, const function &sibling,
105 bool is_method, return_type (*)(arg_type...)) {
106
107 typedef arg_value_caster<arg_type...> cast_in;
108 typedef return_value_caster<return_type> cast_out;
109 struct capture { typename std::remove_reference<func>::type f; };
110 void *ptr = new capture { std::forward<func>(f) };
111
112 auto impl = [](function_entry *entry, PyObject *pyArgs, PyObject *parent) -> PyObject *{
113 cast_in args;
114 if (!args.load(pyArgs, true)) return nullptr;
115 func &f = ((capture *) entry->data)->f;
116 return cast_out::cast(args.template call<return_type>(f),
117 entry->policy, parent);
118 };
119
120 initialize(name, doc, cast_in::name() + std::string(" -> ") + cast_out::name(),
121 sibling, is_method, policy, impl, ptr);
122 }
123
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200124 static PyObject *dispatcher(PyObject *self, PyObject *args, PyObject * /* kwargs */) {
125 function_entry *overloads = (function_entry *) PyCapsule_GetPointer(self, nullptr);
126 PyObject *result = nullptr;
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200127 PyObject *parent = PyTuple_Size(args) > 0 ? PyTuple_GetItem(args, 0) : nullptr;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200128 try {
129 for (function_entry *it = overloads; it != nullptr; it = it->next) {
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200130 if ((result = it->impl(it, args, parent)) != nullptr)
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200131 break;
132 }
133 } catch (const error_already_set &) { return nullptr;
134 } catch (const index_error &e) { PyErr_SetString(PyExc_IndexError, e.what()); return nullptr;
135 } catch (const stop_iteration &e) { PyErr_SetString(PyExc_StopIteration, e.what()); return nullptr;
136 } catch (const std::exception &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); return nullptr;
137 } catch (...) {
138 PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!");
139 return nullptr;
140 }
141 if (result) {
142 if (overloads->is_constructor) {
143 PyObject *inst = PyTuple_GetItem(args, 0);
144 const detail::type_info *type_info =
145 capsule(PyObject_GetAttrString((PyObject *) Py_TYPE(inst),
146 const_cast<char *>("__pybind__")), false);
147 type_info->init_holder(inst);
148 }
149 return result;
150 } else {
151 std::string signatures = "Incompatible function arguments. The "
152 "following argument types are supported:\n";
153 int ctr = 0;
154 for (function_entry *it = overloads; it != nullptr; it = it->next) {
155 signatures += " "+ std::to_string(++ctr) + ". ";
156 signatures += it->signature;
157 signatures += "\n";
158 }
159 PyErr_SetString(PyExc_TypeError, signatures.c_str());
160 return nullptr;
161 }
162 }
163
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200164 void initialize(const char *name, const char *doc,
165 const std::string &signature, function sibling,
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200166 bool is_method, return_value_policy policy,
167 PyObject *(*impl) (function_entry *, PyObject *, PyObject *),
168 void *data) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200169 if (name == nullptr)
170 name = "";
171
172 /* Linked list of function call handlers (for overloading) */
173 function_entry *entry = new function_entry();
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200174 entry->impl = impl;
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200175 entry->is_constructor = !strcmp(name, "__init__");
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200176 entry->policy = policy;
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200177 entry->signature = signature;
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200178 entry->data = data;
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200179 if (doc) entry->doc = doc;
180
181 if (!sibling.ptr() || !PyCFunction_Check(sibling.ptr())) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200182 PyMethodDef *def = new PyMethodDef();
183 memset(def, 0, sizeof(PyMethodDef));
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200184 def->ml_name = name != nullptr ? strdup(name) : name;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200185 def->ml_meth = reinterpret_cast<PyCFunction>(*dispatcher);
186 def->ml_flags = METH_VARARGS | METH_KEYWORDS;
187 capsule entry_capsule(entry);
188 m_ptr = PyCFunction_New(def, entry_capsule.ptr());
189 if (!m_ptr)
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200190 throw std::runtime_error("cpp_function::cpp_function(): Could not allocate function object");
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200191 } else {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200192 m_ptr = sibling.ptr();
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200193 inc_ref();
194 capsule entry_capsule(PyCFunction_GetSelf(m_ptr), true);
195 function_entry *parent = (function_entry *) entry_capsule, *backup = parent;
196 while (parent->next)
197 parent = parent->next;
198 parent->next = entry;
199 entry = backup;
200 }
201 std::string signatures;
Wenzel Jakob2ac80e72015-07-22 00:59:01 +0200202 int it = 0;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200203 while (entry) { /* Create pydoc entry */
Wenzel Jakob2ac80e72015-07-22 00:59:01 +0200204 if (sibling.ptr())
205 signatures += std::to_string(++it) + ". ";
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200206 signatures += "Signature : " + std::string(entry->signature) + "\n";
207 if (!entry->doc.empty())
208 signatures += "\n" + std::string(entry->doc) + "\n";
209 if (entry->next)
210 signatures += "\n";
211 entry = entry->next;
212 }
213 PyCFunctionObject *func = (PyCFunctionObject *) m_ptr;
214 if (func->m_ml->ml_doc)
215 std::free((char *) func->m_ml->ml_doc);
216 func->m_ml->ml_doc = strdup(signatures.c_str());
217 if (is_method) {
218 m_ptr = PyInstanceMethod_New(m_ptr);
219 if (!m_ptr)
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200220 throw std::runtime_error("cpp_function::cpp_function(): Could not allocate instance method object");
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200221 Py_DECREF(func);
222 }
223 }
224};
225
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200226class cpp_method : public cpp_function {
227public:
228 cpp_method () { }
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200229 template <typename func> cpp_method(func &&f, const char *name = nullptr,
230 const char *doc = nullptr, return_value_policy
231 policy = return_value_policy::automatic, function sibling = function())
232 : cpp_function(std::forward<func>(f), name, doc, policy, sibling, true) {}
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200233};
234
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200235class module : public object {
236public:
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200237 PYBIND_OBJECT_DEFAULT(module, object, PyModule_Check)
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200238
239 module(const char *name, const char *doc = nullptr) {
240 PyModuleDef *def = new PyModuleDef();
241 memset(def, 0, sizeof(PyModuleDef));
242 def->m_name = name;
243 def->m_doc = doc;
244 def->m_size = -1;
245 Py_INCREF(def);
246 m_ptr = PyModule_Create(def);
247 if (m_ptr == nullptr)
248 throw std::runtime_error("Internal error in module::module()");
249 inc_ref();
250 }
251
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200252 template <typename Func>
253 module &def(const char *name, Func f, const char *doc = nullptr,
254 return_value_policy policy = return_value_policy::automatic) {
255 cpp_function func(f, name, doc, policy, (function) attr(name));
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200256 func.inc_ref(); /* The following line steals a reference to 'func' */
257 PyModule_AddObject(ptr(), name, func.ptr());
258 return *this;
259 }
260
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200261 module def_submodule(const char *name, const char *doc = nullptr) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200262 std::string full_name = std::string(PyModule_GetName(m_ptr))
263 + std::string(".") + std::string(name);
264 module result(PyImport_AddModule(full_name.c_str()), true);
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200265 if (doc)
266 result.attr("__doc__") = pybind::str(doc);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200267 attr(name) = result;
268 return result;
269 }
270};
271
272NAMESPACE_BEGIN(detail)
273/* Forward declarations */
274enum op_id : int;
275enum op_type : int;
276struct undefined_t;
277template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t> struct op_;
278template <typename ... Args> struct init;
279
280/// Basic support for creating new Python heap types
281class custom_type : public object {
282public:
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200283 PYBIND_OBJECT_DEFAULT(custom_type, object, PyType_Check)
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200284
285 custom_type(object &scope, const char *name_, const std::string &type_name,
286 size_t type_size, size_t instance_size,
287 void (*init_holder)(PyObject *), const destructor &dealloc,
288 PyObject *parent, const char *doc) {
289 PyHeapTypeObject *type = (PyHeapTypeObject*) PyType_Type.tp_alloc(&PyType_Type, 0);
290 PyObject *name = PyUnicode_FromString(name_);
291 if (type == nullptr || name == nullptr)
292 throw std::runtime_error("Internal error in custom_type::custom_type()");
293 Py_INCREF(name);
294 std::string full_name(name_);
295
296 pybind::str scope_name = (object) scope.attr("__name__"),
297 module_name = (object) scope.attr("__module__");
298
299 if (scope_name.check())
300 full_name = std::string(scope_name) + "." + full_name;
301 if (module_name.check())
302 full_name = std::string(module_name) + "." + full_name;
303
304 type->ht_name = type->ht_qualname = name;
305 type->ht_type.tp_name = strdup(full_name.c_str());
306 type->ht_type.tp_basicsize = instance_size;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200307 type->ht_type.tp_init = (initproc) init;
308 type->ht_type.tp_new = (newfunc) new_instance;
309 type->ht_type.tp_dealloc = dealloc;
310 type->ht_type.tp_flags |=
311 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
312 type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC;
313 type->ht_type.tp_as_number = &type->as_number;
314 type->ht_type.tp_as_sequence = &type->as_sequence;
315 type->ht_type.tp_as_mapping = &type->as_mapping;
316 type->ht_type.tp_base = (PyTypeObject *) parent;
317 Py_XINCREF(parent);
318
319 if (PyType_Ready(&type->ht_type) < 0)
320 throw std::runtime_error("Internal error in custom_type::custom_type()");
321 m_ptr = (PyObject *) type;
322
323 /* Needed by pydoc */
324 if (((module &) scope).check())
325 attr("__module__") = scope_name;
326
327 auto &type_info = detail::get_internals().registered_types[type_name];
328 type_info.type = (PyTypeObject *) m_ptr;
329 type_info.type_size = type_size;
330 type_info.init_holder = init_holder;
331 attr("__pybind__") = capsule(&type_info);
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200332 if (doc)
333 attr("__doc__") = pybind::str(doc);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200334
335 scope.attr(name) = *this;
336 }
337
338protected:
339 /* Allocate a metaclass on demand (for static properties) */
340 handle metaclass() {
341 auto &ht_type = ((PyHeapTypeObject *) m_ptr)->ht_type;
342 auto &ob_type = ht_type.ob_base.ob_base.ob_type;
343 if (ob_type == &PyType_Type) {
344 std::string name_ = std::string(ht_type.tp_name) + "_meta";
345 PyHeapTypeObject *type = (PyHeapTypeObject*) PyType_Type.tp_alloc(&PyType_Type, 0);
346 PyObject *name = PyUnicode_FromString(name_.c_str());
347 if (type == nullptr || name == nullptr)
348 throw std::runtime_error("Internal error in custom_type::metaclass()");
349 Py_INCREF(name);
350 type->ht_name = type->ht_qualname = name;
351 type->ht_type.tp_name = strdup(name_.c_str());
352 type->ht_type.tp_base = &PyType_Type;
353 type->ht_type.tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE;
354 type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC;
355 if (PyType_Ready(&type->ht_type) < 0)
356 throw std::runtime_error("Internal error in custom_type::metaclass()");
357 ob_type = (PyTypeObject *) type;
358 Py_INCREF(type);
359 }
360 return handle((PyObject *) ob_type);
361 }
362
363 static int init(void *self, PyObject *, PyObject *) {
364 std::string msg = std::string(Py_TYPE(self)->tp_name) + ": No constructor defined!";
365 PyErr_SetString(PyExc_TypeError, msg.c_str());
366 return -1;
367 }
368
369 static PyObject *new_instance(PyTypeObject *type, PyObject *, PyObject *) {
370 const detail::type_info *type_info = capsule(
371 PyObject_GetAttrString((PyObject *) type, const_cast<char*>("__pybind__")), false);
372 instance<void> *self = (instance<void> *) PyType_GenericAlloc(type, 0);
373 self->value = ::operator new(type_info->type_size);
374 self->owned = true;
375 self->parent = nullptr;
376 self->constructed = false;
377 detail::get_internals().registered_instances[self->value] = (PyObject *) self;
378 return (PyObject *) self;
379 }
380
381 static void dealloc(instance<void> *self) {
382 if (self->value) {
383 bool dont_cache = self->parent && ((instance<void> *) self->parent)->value == self->value;
384 if (!dont_cache) { // avoid an issue with internal references matching their parent's address
385 auto &registered_instances = detail::get_internals().registered_instances;
386 auto it = registered_instances.find(self->value);
387 if (it == registered_instances.end())
388 throw std::runtime_error("Deallocating unregistered instance!");
389 registered_instances.erase(it);
390 }
391 Py_XDECREF(self->parent);
392 }
393 Py_TYPE(self)->tp_free((PyObject*) self);
394 }
395
396 void install_buffer_funcs(const std::function<buffer_info *(PyObject *)> &func) {
397 PyHeapTypeObject *type = (PyHeapTypeObject*) m_ptr;
398 type->ht_type.tp_as_buffer = &type->as_buffer;
399 type->as_buffer.bf_getbuffer = getbuffer;
400 type->as_buffer.bf_releasebuffer = releasebuffer;
401 ((detail::type_info *) capsule(attr("__pybind__")))->get_buffer = func;
402 }
403
404 static int getbuffer(PyObject *obj, Py_buffer *view, int flags) {
405 auto const &info_func = ((detail::type_info *) capsule(handle(obj).attr("__pybind__")))->get_buffer;
406 if (view == nullptr || obj == nullptr || !info_func) {
407 PyErr_SetString(PyExc_BufferError, "Internal error");
408 return -1;
409 }
410 memset(view, 0, sizeof(Py_buffer));
411 buffer_info *info = info_func(obj);
412 view->obj = obj;
413 view->ndim = 1;
414 view->internal = info;
415 view->buf = info->ptr;
416 view->itemsize = info->itemsize;
417 view->len = view->itemsize;
418 for (auto s : info->shape)
419 view->len *= s;
420 if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT)
421 view->format = const_cast<char *>(info->format.c_str());
422 if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
423 view->ndim = info->ndim;
424 view->strides = (Py_ssize_t *)&info->strides[0];
425 view->shape = (Py_ssize_t *) &info->shape[0];
426 }
427 Py_INCREF(view->obj);
428 return 0;
429 }
430
431 static void releasebuffer(PyObject *, Py_buffer *view) { delete (buffer_info *) view->internal; }
432};
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200433NAMESPACE_END(detail)
434
435template <typename type, typename holder_type = std::unique_ptr<type>> class class_ : public detail::custom_type {
436public:
437 typedef detail::instance<type, holder_type> instance_type;
438
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200439 PYBIND_OBJECT(class_, detail::custom_type, PyType_Check)
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200440
441 class_(object &scope, const char *name, const char *doc = nullptr)
442 : detail::custom_type(scope, name, type_id<type>(), sizeof(type),
443 sizeof(instance_type), init_holder, dealloc,
444 nullptr, doc) { }
445
446 class_(object &scope, const char *name, object &parent,
447 const char *doc = nullptr)
448 : detail::custom_type(scope, name, type_id<type>(), sizeof(type),
449 sizeof(instance_type), init_holder, dealloc,
450 parent.ptr(), doc) { }
451
452 template <typename Func>
453 class_ &def(const char *name, Func f, const char *doc = nullptr,
454 return_value_policy policy = return_value_policy::automatic) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200455 attr(name) = cpp_method(f, name, doc, policy, (function) attr(name));
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200456 return *this;
457 }
458
459 template <typename Func> class_ &
460 def_static(const char *name, Func f, const char *doc = nullptr,
461 return_value_policy policy = return_value_policy::automatic) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200462 attr(name) = cpp_function(f, name, doc, policy, (function) attr(name));
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200463 return *this;
464 }
465
466 template <detail::op_id id, detail::op_type ot, typename L, typename R>
467 class_ &def(const detail::op_<id, ot, L, R> &op, const char *doc = nullptr,
468 return_value_policy policy = return_value_policy::automatic) {
469 op.template execute<type>(*this, doc, policy);
470 return *this;
471 }
472
473 template <detail::op_id id, detail::op_type ot, typename L, typename R> class_ &
474 def_cast(const detail::op_<id, ot, L, R> &op, const char *doc = nullptr,
475 return_value_policy policy = return_value_policy::automatic) {
476 op.template execute_cast<type>(*this, doc, policy);
477 return *this;
478 }
479
480 template <typename... Args>
481 class_ &def(const detail::init<Args...> &init, const char *doc = nullptr) {
482 init.template execute<type>(*this, doc);
483 return *this;
484 }
485
486 class_& def_buffer(const std::function<buffer_info(type&)> &func) {
487 install_buffer_funcs([func](PyObject *obj) -> buffer_info* {
488 detail::type_caster<type> caster;
489 if (!caster.load(obj, false))
490 return nullptr;
491 return new buffer_info(func(caster));
492 });
493 return *this;
494 }
495
496 template <typename C, typename D>
497 class_ &def_readwrite(const char *name, D C::*pm,
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200498 const char *doc = nullptr) {
499 cpp_method fget([pm](const C &c) -> const D &{ return c.*pm; }, nullptr,
500 nullptr, return_value_policy::reference_internal),
501 fset([pm](C &c, const D &value) { c.*pm = value; });
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200502 def_property(name, fget, fset, doc);
503 return *this;
504 }
505
506 template <typename C, typename D>
507 class_ &def_readonly(const char *name, const D C::*pm,
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200508 const char *doc = nullptr) {
509 cpp_method fget([pm](const C &c) -> const D &{ return c.*pm; }, nullptr,
510 nullptr, return_value_policy::reference_internal);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200511 def_property(name, fget, doc);
512 return *this;
513 }
514
515 template <typename D>
516 class_ &def_readwrite_static(const char *name, D *pm,
517 const char *doc = nullptr) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200518 cpp_function fget([pm](object) -> const D &{ return *pm; }, nullptr,
519 nullptr, return_value_policy::reference_internal),
520 fset([pm](object, const D &value) { *pm = value; });
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200521 def_property_static(name, fget, fset, doc);
522 return *this;
523 }
524
525 template <typename D>
526 class_ &def_readonly_static(const char *name, const D *pm,
527 const char *doc = nullptr) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200528 cpp_function fget([pm](object) -> const D &{ return *pm; }, nullptr,
529 nullptr, return_value_policy::reference_internal);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200530 def_property_static(name, fget, doc);
531 return *this;
532 }
533
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200534 class_ &def_property(const char *name, const cpp_method &fget,
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200535 const char *doc = nullptr) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200536 def_property(name, fget, cpp_method(), doc);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200537 return *this;
538 }
539
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200540 class_ &def_property_static(const char *name, const cpp_function &fget,
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200541 const char *doc = nullptr) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200542 def_property_static(name, fget, cpp_function(), doc);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200543 return *this;
544 }
545
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200546 class_ &def_property(const char *name, const cpp_method &fget,
547 const cpp_method &fset, const char *doc = nullptr) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200548 object property(
549 PyObject_CallFunction((PyObject *)&PyProperty_Type,
550 const_cast<char *>("OOOs"), fget.ptr() ? fget.ptr() : Py_None,
551 fset.ptr() ? fset.ptr() : Py_None, Py_None, doc), false);
552 attr(name) = property;
553 return *this;
554 }
555
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200556 class_ &def_property_static(const char *name, const cpp_function &fget,
557 const cpp_function &fset,
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200558 const char *doc = nullptr) {
559 object property(
560 PyObject_CallFunction((PyObject *)&PyProperty_Type,
561 const_cast<char *>("OOOs"), fget.ptr() ? fget.ptr() : Py_None,
562 fset.ptr() ? fset.ptr() : Py_None, Py_None, doc), false);
563 metaclass().attr(name) = property;
564 return *this;
565 }
566private:
567 static void init_holder(PyObject *inst_) {
568 instance_type *inst = (instance_type *) inst_;
569 new (&inst->holder) holder_type(inst->value);
570 inst->constructed = true;
571 }
572 static void dealloc(PyObject *inst_) {
573 instance_type *inst = (instance_type *) inst_;
574 if (inst->owned) {
575 if (inst->constructed)
576 inst->holder.~holder_type();
577 else
578 ::operator delete(inst->value);
579 }
580 custom_type::dealloc((detail::instance<void> *) inst);
581 }
582};
583
584/// Binds C++ enumerations and enumeration classes to Python
585template <typename Type> class enum_ : public class_<Type> {
586public:
587 enum_(object &scope, const char *name, const char *doc = nullptr)
588 : class_<Type>(scope, name, doc), m_parent(scope) {
589 auto entries = new std::unordered_map<int, const char *>();
590 this->def("__str__", [name, entries](Type value) -> std::string {
591 auto it = entries->find(value);
592 return std::string(name) + "." +
593 ((it == entries->end()) ? std::string("???")
594 : std::string(it->second));
595 });
596 m_entries = entries;
597 }
598
599 /// Export enumeration entries into the parent scope
600 void export_values() {
601 PyObject *dict = ((PyTypeObject *) this->m_ptr)->tp_dict;
602 PyObject *key, *value;
603 Py_ssize_t pos = 0;
604 while (PyDict_Next(dict, &pos, &key, &value))
605 if (PyObject_IsInstance(value, this->m_ptr))
606 m_parent.attr(key) = value;
607 }
608
609 /// Add an enumeration entry
610 enum_& value(char const* name, Type value) {
611 this->attr(name) = pybind::cast(value, return_value_policy::copy);
612 (*m_entries)[(int) value] = name;
613 return *this;
614 }
615private:
616 std::unordered_map<int, const char *> *m_entries;
617 object &m_parent;
618};
619
620NAMESPACE_BEGIN(detail)
621template <typename ... Args> struct init {
622 template <typename Base, typename Holder> void execute(pybind::class_<Base, Holder> &class_, const char *doc) const {
623 /// Function which calls a specific C++ in-place constructor
624 class_.def("__init__", [](Base *instance, Args... args) { new (instance) Base(args...); }, doc);
625 }
626};
627NAMESPACE_END(detail)
628
629template <typename... Args> detail::init<Args...> init() { return detail::init<Args...>(); };
630
631template <typename InputType, typename OutputType> void implicitly_convertible() {
632 auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject *{
633 if (!detail::type_caster<InputType>().load(obj, false))
634 return nullptr;
635 tuple args(1);
636 args[0] = obj;
637 PyObject *result = PyObject_Call((PyObject *) type, args.ptr(), nullptr);
638 if (result == nullptr)
639 PyErr_Clear();
640 return result;
641 };
642 std::string output_type_name = type_id<OutputType>();
643 auto & registered_types = detail::get_internals().registered_types;
644 auto it = registered_types.find(output_type_name);
645 if (it == registered_types.end())
646 throw std::runtime_error("implicitly_convertible: Unable to find type " + output_type_name);
647 it->second.implicit_conversions.push_back(implicit_caster);
648}
649
650inline void init_threading() { PyEval_InitThreads(); }
651
652class gil_scoped_acquire {
653 PyGILState_STATE state;
654public:
655 inline gil_scoped_acquire() { state = PyGILState_Ensure(); }
656 inline ~gil_scoped_acquire() { PyGILState_Release(state); }
657};
658
659class gil_scoped_release {
660 PyThreadState *state;
661public:
662 inline gil_scoped_release() { state = PyEval_SaveThread(); }
663 inline ~gil_scoped_release() { PyEval_RestoreThread(state); }
664};
665
666NAMESPACE_END(pybind)
667
668#if defined(_MSC_VER)
669#pragma warning(pop)
670#endif