blob: 64ae5a0ddf4299187698d41027ec031c02a003bd [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 Jakob71867832015-07-29 17:43:52 +020025template <typename T> struct arg_t;
26
27/// Annotation for keyword arguments
28struct arg {
29 arg(const char *name) : name(name) { }
30 template <typename T> inline arg_t<T> operator=(const T &value);
31 const char *name;
32};
33
34/// Annotation for keyword arguments with default values
35template <typename T> struct arg_t : public arg {
36 arg_t(const char *name, const T &value) : arg(name), value(value) { }
37 T value;
38};
39template <typename T> inline arg_t<T> arg::operator=(const T &value) { return arg_t<T>(name, value); }
40
41/// Annotation for methods
42struct is_method { };
43
44/// Annotation for documentation
45struct doc { const char *value; doc(const char *value) : value(value) { } };
46
47/// Annotation for function names
48struct name { const char *value; name(const char *value) : value(value) { } };
49
50/// Annotation for function siblings
51struct sibling { PyObject *value; sibling(handle value) : value(value.ptr()) { } };
52
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020053/// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object
Wenzel Jakobbd4a5292015-07-11 17:41:48 +020054class cpp_function : public function {
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020055private:
56 /// Chained list of function entries for overloading
Wenzel Jakob38bd7112015-07-05 20:05:44 +020057 struct function_entry {
Wenzel Jakob71867832015-07-29 17:43:52 +020058 const char *name = nullptr;
59 PyObject * (*impl) (function_entry *, PyObject *, PyObject *, PyObject *);
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020060 void *data;
Wenzel Jakob71867832015-07-29 17:43:52 +020061 bool is_constructor = false, is_method = false;
62 short keywords = 0;
63 return_value_policy policy = return_value_policy::automatic;
64 std::string signature;
65 PyObject *sibling = nullptr;
66 const char *doc = nullptr;
Wenzel Jakob38bd7112015-07-05 20:05:44 +020067 function_entry *next = nullptr;
68 };
Wenzel Jakob38bd7112015-07-05 20:05:44 +020069
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020070 /// Picks a suitable return value converter from cast.h
71 template <typename T> using return_value_caster =
72 detail::type_caster<typename std::conditional<
73 std::is_void<T>::value, detail::void_type, typename detail::decay<T>::type>::type>;
74
75 /// Picks a suitable argument value converter from cast.h
Wenzel Jakob71867832015-07-29 17:43:52 +020076 template <typename... T> using arg_value_caster =
Wenzel Jakobd4258ba2015-07-26 16:33:49 +020077 detail::type_caster<typename std::tuple<T...>>;
Wenzel Jakob71867832015-07-29 17:43:52 +020078
Wenzel Jakoba576e6a2015-07-29 17:51:54 +020079 template <typename... T> static void process_extras(const std::tuple<T...> &args,
80 function_entry *entry, const char **kw, const char **def) {
81 process_extras(args, entry, kw, def, typename detail::make_index_sequence<sizeof...(T)>::type());
Wenzel Jakob71867832015-07-29 17:43:52 +020082 }
83
Wenzel Jakoba576e6a2015-07-29 17:51:54 +020084 template <typename... T, size_t ... Index> static void process_extras(const std::tuple<T...> &args,
85 function_entry *entry, const char **kw, const char **def, detail::index_sequence<Index...>) {
86 int unused[] = { 0, (process_extra(std::get<Index>(args), entry, kw, def), 0)... };
Wenzel Jakob71867832015-07-29 17:43:52 +020087 (void) unused;
88 }
89
Wenzel Jakoba576e6a2015-07-29 17:51:54 +020090 template <typename... T> static void process_extras(const std::tuple<T...> &args,
91 PyObject *pyArgs, PyObject *kwargs, bool is_method) {
92 process_extras(args, pyArgs, kwargs, is_method, typename detail::make_index_sequence<sizeof...(T)>::type());
93 }
Wenzel Jakob71867832015-07-29 17:43:52 +020094
Wenzel Jakoba576e6a2015-07-29 17:51:54 +020095 template <typename... T, size_t... Index> static void process_extras(const std::tuple<T...> &args,
96 PyObject *pyArgs, PyObject *kwargs, bool is_method, detail::index_sequence<Index...>) {
97 int index = is_method ? 1 : 0;
98 int unused[] = { 0, (process_extra(std::get<Index>(args), index, pyArgs, kwargs), 0)... };
99 (void) unused;
100 }
101
102 static void process_extra(const char *doc, function_entry *entry, const char **, const char **) { entry->doc = doc; }
103 static void process_extra(const pybind::doc &d, function_entry *entry, const char **, const char **) { entry->doc = d.value; }
104 static void process_extra(const pybind::name &n, function_entry *entry, const char **, const char **) { entry->name = n.value; }
105 static void process_extra(const pybind::arg &a, function_entry *entry, const char **kw, const char **) {
106 if (entry->is_method && entry->keywords == 0)
107 kw[entry->keywords++] = "self";
108 kw[entry->keywords++] = a.name;
109 }
110 template <typename T>
111 static void process_extra(const pybind::arg_t<T> &a, function_entry *entry, const char **kw, const char **def) {
112 if (entry->is_method && entry->keywords == 0)
113 kw[entry->keywords++] = "self";
114 kw[entry->keywords] = a.name;
115 def[entry->keywords++] = strdup(std::to_string(a.value).c_str());
116 }
117
118 static void process_extra(const pybind::is_method &, function_entry *entry, const char **, const char **) { entry->is_method = true; }
119 static void process_extra(const pybind::return_value_policy p, function_entry *entry, const char **, const char **) { entry->policy = p; }
120 static void process_extra(pybind::sibling s, function_entry *entry, const char **, const char **) { entry->sibling = s.value; }
121
122 template <typename T> static void process_extra(T, int &, PyObject *, PyObject *) { }
123 static void process_extra(const pybind::arg &a, int &index, PyObject *args, PyObject *kwargs) {
124 if (kwargs) {
125 if (PyTuple_GET_ITEM(args, index) != nullptr) {
126 index++;
127 return;
128 }
129 PyObject *value = PyDict_GetItemString(kwargs, a.name);
130 if (value) {
131 Py_INCREF(value);
132 PyTuple_SetItem(args, index, value);
133 }
134 }
135 index++;
136 }
137 template <typename T>
138 static void process_extra(const pybind::arg_t<T> &a, int &index, PyObject *args, PyObject *kwargs) {
139 if (PyTuple_GET_ITEM(args, index) != nullptr) {
140 index++;
141 return;
142 }
143 PyObject *value = nullptr;
144 if (kwargs)
145 value = PyDict_GetItemString(kwargs, a.name);
146 if (value) {
147 Py_INCREF(value);
148 } else {
149 value = detail::type_caster<typename detail::decay<T>::type>::cast(
150 a.value, return_value_policy::automatic, nullptr);
151 }
152 PyTuple_SetItem(args, index, value);
153 index++;
154 }
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200155public:
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200156 cpp_function() { }
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200157
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200158 /// Vanilla function pointers
Wenzel Jakob71867832015-07-29 17:43:52 +0200159 template <typename Return, typename... Arg, typename... Extra>
160 cpp_function(Return (*f)(Arg...), Extra&&... extra) {
161 struct capture {
162 Return (*f)(Arg...);
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200163 std::tuple<Extra...> extras;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200164 };
165
Wenzel Jakob71867832015-07-29 17:43:52 +0200166 function_entry *entry = new function_entry();
167 entry->data = new capture { f, std::tuple<Extra...>(std::forward<Extra>(extra)...) };
168
169 typedef arg_value_caster<Arg...> cast_in;
170 typedef return_value_caster<Return> cast_out;
171
172 entry->impl = [](function_entry *entry, PyObject *pyArgs, PyObject *kwargs, PyObject *parent) -> PyObject * {
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200173 capture *data = (capture *) entry->data;
174 process_extras(data->extras, pyArgs, kwargs, entry->is_method);
Wenzel Jakob71867832015-07-29 17:43:52 +0200175 cast_in args;
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200176 if (!args.load(pyArgs, true))
177 return nullptr;
178 return cast_out::cast(args.template call<Return>(data->f), entry->policy, parent);
Wenzel Jakob71867832015-07-29 17:43:52 +0200179 };
180
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200181 const int N = sizeof...(Extra) > sizeof...(Arg) ? sizeof...(Extra) : sizeof...(Arg);
182 std::array<const char *, N> kw{}, def{};
183 process_extras(((capture *) entry->data)->extras, entry, kw.data(), def.data());
184
185 entry->signature = cast_in::name(kw.data(), def.data());
Wenzel Jakob71867832015-07-29 17:43:52 +0200186 entry->signature += " -> ";
187 entry->signature += cast_out::name();
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200188
189 initialize(entry, sizeof...(Arg));
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200190 }
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200191
192 /// Delegating helper constructor to deal with lambda functions
Wenzel Jakob71867832015-07-29 17:43:52 +0200193 template <typename Func, typename... Extra> cpp_function(Func &&f, Extra&&... extra) {
194 initialize(std::forward<Func>(f),
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200195 (typename detail::remove_class<decltype(
Wenzel Jakob71867832015-07-29 17:43:52 +0200196 &std::remove_reference<Func>::type::operator())>::type *) nullptr,
197 std::forward<Extra>(extra)...);
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200198 }
199
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200200 /// Class methods (non-const)
Wenzel Jakob71867832015-07-29 17:43:52 +0200201 template <typename Return, typename Class, typename... Arg, typename... Extra> cpp_function(
202 Return (Class::*f)(Arg...), Extra&&... extra) {
203 initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); },
204 (Return (*) (Class *, Arg...)) nullptr, std::forward<Extra>(extra)...);
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200205 }
206
207 /// Class methods (const)
Wenzel Jakob71867832015-07-29 17:43:52 +0200208 template <typename Return, typename Class, typename... Arg, typename... Extra> cpp_function(
209 Return (Class::*f)(Arg...) const, Extra&&... extra) {
210 initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); },
211 (Return (*)(const Class *, Arg ...)) nullptr, std::forward<Extra>(extra)...);
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200212 }
213
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200214private:
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200215 /// Functors, lambda functions, etc.
Wenzel Jakob71867832015-07-29 17:43:52 +0200216 template <typename Func, typename Return, typename... Arg, typename... Extra>
217 void initialize(Func &&f, Return (*)(Arg...), Extra&&... extra) {
218 struct capture {
219 typename std::remove_reference<Func>::type f;
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200220 std::tuple<Extra...> extras;
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200221 };
222
Wenzel Jakob71867832015-07-29 17:43:52 +0200223 function_entry *entry = new function_entry();
224 entry->data = new capture { std::forward<Func>(f), std::tuple<Extra...>(std::forward<Extra>(extra)...) };
225
226 typedef arg_value_caster<Arg...> cast_in;
227 typedef return_value_caster<Return> cast_out;
228
229 entry->impl = [](function_entry *entry, PyObject *pyArgs, PyObject *kwargs, PyObject *parent) -> PyObject *{
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200230 capture *data = (capture *)entry->data;
231 process_extras(data->extras, pyArgs, kwargs, entry->is_method);
Wenzel Jakob71867832015-07-29 17:43:52 +0200232 cast_in args;
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200233 if (!args.load(pyArgs, true))
234 return nullptr;
235 return cast_out::cast(args.template call<Return>(data->f), entry->policy, parent);
Wenzel Jakob71867832015-07-29 17:43:52 +0200236 };
237
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200238 const int N = sizeof...(Extra) > sizeof...(Arg) ? sizeof...(Extra) : sizeof...(Arg);
239 std::array<const char *, N> kw{}, def{};
240 process_extras(((capture *) entry->data)->extras, entry, kw.data(), def.data());
241
242 entry->signature = cast_in::name(kw.data(), def.data());
Wenzel Jakob71867832015-07-29 17:43:52 +0200243 entry->signature += " -> ";
244 entry->signature += cast_out::name();
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200245
246 initialize(entry, sizeof...(Arg));
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200247 }
248
Wenzel Jakob71867832015-07-29 17:43:52 +0200249 static PyObject *dispatcher(PyObject *self, PyObject *args, PyObject *kwargs ) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200250 function_entry *overloads = (function_entry *) PyCapsule_GetPointer(self, nullptr);
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200251 int nargs = (int) PyTuple_Size(args);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200252 PyObject *result = nullptr;
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200253 PyObject *parent = nargs > 0 ? PyTuple_GetItem(args, 0) : nullptr;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200254 try {
255 for (function_entry *it = overloads; it != nullptr; it = it->next) {
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200256 PyObject *args_ = args;
257
258 if (it->keywords != 0 && it->keywords != nargs) {
259 args_ = PyTuple_New(it->keywords);
260 for (int i=0; i<nargs; ++i) {
261 PyObject *item = PyTuple_GET_ITEM(args, i);
262 Py_INCREF(item);
263 PyTuple_SET_ITEM(args_, i, item);
264 }
265 }
266
267 result = it->impl(it, args_, kwargs, parent);
268
269 if (args_ != args) {
270 Py_DECREF(args_);
271 }
272
273 if (result != nullptr)
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200274 break;
275 }
276 } catch (const error_already_set &) { return nullptr;
277 } catch (const index_error &e) { PyErr_SetString(PyExc_IndexError, e.what()); return nullptr;
278 } catch (const stop_iteration &e) { PyErr_SetString(PyExc_StopIteration, e.what()); return nullptr;
279 } catch (const std::exception &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); return nullptr;
280 } catch (...) {
281 PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!");
282 return nullptr;
283 }
284 if (result) {
285 if (overloads->is_constructor) {
286 PyObject *inst = PyTuple_GetItem(args, 0);
287 const detail::type_info *type_info =
288 capsule(PyObject_GetAttrString((PyObject *) Py_TYPE(inst),
289 const_cast<char *>("__pybind__")), false);
290 type_info->init_holder(inst);
291 }
292 return result;
293 } else {
294 std::string signatures = "Incompatible function arguments. The "
295 "following argument types are supported:\n";
296 int ctr = 0;
297 for (function_entry *it = overloads; it != nullptr; it = it->next) {
298 signatures += " "+ std::to_string(++ctr) + ". ";
299 signatures += it->signature;
300 signatures += "\n";
301 }
302 PyErr_SetString(PyExc_TypeError, signatures.c_str());
303 return nullptr;
304 }
305 }
306
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200307 void initialize(function_entry *entry, int args) {
Wenzel Jakob71867832015-07-29 17:43:52 +0200308 if (entry->name == nullptr)
309 entry->name = "";
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200310 if (entry->keywords != 0 && entry->keywords != args)
311 throw std::runtime_error(
312 "cpp_function(): function \"" + std::string(entry->name) + "\" takes " +
313 std::to_string(args) + " arguments, but " + std::to_string(entry->keywords) +
314 " pybind::arg entries were specified!");
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200315
Wenzel Jakob71867832015-07-29 17:43:52 +0200316 entry->is_constructor = !strcmp(entry->name, "__init__");
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200317
Wenzel Jakob71867832015-07-29 17:43:52 +0200318 if (!entry->sibling || !PyCFunction_Check(entry->sibling)) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200319 PyMethodDef *def = new PyMethodDef();
320 memset(def, 0, sizeof(PyMethodDef));
Wenzel Jakob71867832015-07-29 17:43:52 +0200321 def->ml_name = entry->name;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200322 def->ml_meth = reinterpret_cast<PyCFunction>(*dispatcher);
323 def->ml_flags = METH_VARARGS | METH_KEYWORDS;
324 capsule entry_capsule(entry);
325 m_ptr = PyCFunction_New(def, entry_capsule.ptr());
326 if (!m_ptr)
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200327 throw std::runtime_error("cpp_function::cpp_function(): Could not allocate function object");
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200328 } else {
Wenzel Jakob71867832015-07-29 17:43:52 +0200329 m_ptr = entry->sibling;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200330 inc_ref();
331 capsule entry_capsule(PyCFunction_GetSelf(m_ptr), true);
332 function_entry *parent = (function_entry *) entry_capsule, *backup = parent;
333 while (parent->next)
334 parent = parent->next;
335 parent->next = entry;
336 entry = backup;
337 }
338 std::string signatures;
Wenzel Jakob71867832015-07-29 17:43:52 +0200339 int index = 0;
340 function_entry *it = entry;
341 while (it) { /* Create pydoc it */
342 if (it->sibling)
343 signatures += std::to_string(++index) + ". ";
344 signatures += "Signature : " + std::string(it->signature) + "\n";
345 if (it->doc && strlen(it->doc) > 0)
346 signatures += "\n" + std::string(it->doc) + "\n";
347 if (it->next)
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200348 signatures += "\n";
Wenzel Jakob71867832015-07-29 17:43:52 +0200349 it = it->next;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200350 }
351 PyCFunctionObject *func = (PyCFunctionObject *) m_ptr;
352 if (func->m_ml->ml_doc)
353 std::free((char *) func->m_ml->ml_doc);
354 func->m_ml->ml_doc = strdup(signatures.c_str());
Wenzel Jakob71867832015-07-29 17:43:52 +0200355 if (entry->is_method) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200356 m_ptr = PyInstanceMethod_New(m_ptr);
357 if (!m_ptr)
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200358 throw std::runtime_error("cpp_function::cpp_function(): Could not allocate instance method object");
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200359 Py_DECREF(func);
360 }
361 }
362};
363
364class module : public object {
365public:
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200366 PYBIND_OBJECT_DEFAULT(module, object, PyModule_Check)
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200367
368 module(const char *name, const char *doc = nullptr) {
369 PyModuleDef *def = new PyModuleDef();
370 memset(def, 0, sizeof(PyModuleDef));
371 def->m_name = name;
372 def->m_doc = doc;
373 def->m_size = -1;
374 Py_INCREF(def);
375 m_ptr = PyModule_Create(def);
376 if (m_ptr == nullptr)
377 throw std::runtime_error("Internal error in module::module()");
378 inc_ref();
379 }
380
Wenzel Jakob71867832015-07-29 17:43:52 +0200381 template <typename Func, typename... Extra>
382 module &def(const char *name_, Func &&f, Extra&& ... extra) {
383 cpp_function func(std::forward<Func>(f), name(name_),
384 sibling((handle) attr(name_)), std::forward<Extra>(extra)...);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200385 func.inc_ref(); /* The following line steals a reference to 'func' */
Wenzel Jakob71867832015-07-29 17:43:52 +0200386 PyModule_AddObject(ptr(), name_, func.ptr());
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200387 return *this;
388 }
389
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200390 module def_submodule(const char *name, const char *doc = nullptr) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200391 std::string full_name = std::string(PyModule_GetName(m_ptr))
392 + std::string(".") + std::string(name);
393 module result(PyImport_AddModule(full_name.c_str()), true);
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200394 if (doc)
395 result.attr("__doc__") = pybind::str(doc);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200396 attr(name) = result;
397 return result;
398 }
399};
400
401NAMESPACE_BEGIN(detail)
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200402/// Basic support for creating new Python heap types
403class custom_type : public object {
404public:
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200405 PYBIND_OBJECT_DEFAULT(custom_type, object, PyType_Check)
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200406
407 custom_type(object &scope, const char *name_, const std::string &type_name,
408 size_t type_size, size_t instance_size,
409 void (*init_holder)(PyObject *), const destructor &dealloc,
410 PyObject *parent, const char *doc) {
411 PyHeapTypeObject *type = (PyHeapTypeObject*) PyType_Type.tp_alloc(&PyType_Type, 0);
412 PyObject *name = PyUnicode_FromString(name_);
413 if (type == nullptr || name == nullptr)
414 throw std::runtime_error("Internal error in custom_type::custom_type()");
415 Py_INCREF(name);
416 std::string full_name(name_);
417
418 pybind::str scope_name = (object) scope.attr("__name__"),
419 module_name = (object) scope.attr("__module__");
420
421 if (scope_name.check())
422 full_name = std::string(scope_name) + "." + full_name;
423 if (module_name.check())
424 full_name = std::string(module_name) + "." + full_name;
425
426 type->ht_name = type->ht_qualname = name;
427 type->ht_type.tp_name = strdup(full_name.c_str());
428 type->ht_type.tp_basicsize = instance_size;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200429 type->ht_type.tp_init = (initproc) init;
430 type->ht_type.tp_new = (newfunc) new_instance;
431 type->ht_type.tp_dealloc = dealloc;
432 type->ht_type.tp_flags |=
433 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
434 type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC;
435 type->ht_type.tp_as_number = &type->as_number;
436 type->ht_type.tp_as_sequence = &type->as_sequence;
437 type->ht_type.tp_as_mapping = &type->as_mapping;
438 type->ht_type.tp_base = (PyTypeObject *) parent;
439 Py_XINCREF(parent);
440
441 if (PyType_Ready(&type->ht_type) < 0)
442 throw std::runtime_error("Internal error in custom_type::custom_type()");
443 m_ptr = (PyObject *) type;
444
445 /* Needed by pydoc */
446 if (((module &) scope).check())
447 attr("__module__") = scope_name;
448
449 auto &type_info = detail::get_internals().registered_types[type_name];
450 type_info.type = (PyTypeObject *) m_ptr;
451 type_info.type_size = type_size;
452 type_info.init_holder = init_holder;
453 attr("__pybind__") = capsule(&type_info);
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200454 if (doc)
455 attr("__doc__") = pybind::str(doc);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200456
457 scope.attr(name) = *this;
458 }
459
460protected:
461 /* Allocate a metaclass on demand (for static properties) */
462 handle metaclass() {
463 auto &ht_type = ((PyHeapTypeObject *) m_ptr)->ht_type;
464 auto &ob_type = ht_type.ob_base.ob_base.ob_type;
465 if (ob_type == &PyType_Type) {
466 std::string name_ = std::string(ht_type.tp_name) + "_meta";
467 PyHeapTypeObject *type = (PyHeapTypeObject*) PyType_Type.tp_alloc(&PyType_Type, 0);
468 PyObject *name = PyUnicode_FromString(name_.c_str());
469 if (type == nullptr || name == nullptr)
470 throw std::runtime_error("Internal error in custom_type::metaclass()");
471 Py_INCREF(name);
472 type->ht_name = type->ht_qualname = name;
473 type->ht_type.tp_name = strdup(name_.c_str());
474 type->ht_type.tp_base = &PyType_Type;
475 type->ht_type.tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE;
476 type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC;
477 if (PyType_Ready(&type->ht_type) < 0)
478 throw std::runtime_error("Internal error in custom_type::metaclass()");
479 ob_type = (PyTypeObject *) type;
480 Py_INCREF(type);
481 }
482 return handle((PyObject *) ob_type);
483 }
484
485 static int init(void *self, PyObject *, PyObject *) {
486 std::string msg = std::string(Py_TYPE(self)->tp_name) + ": No constructor defined!";
487 PyErr_SetString(PyExc_TypeError, msg.c_str());
488 return -1;
489 }
490
491 static PyObject *new_instance(PyTypeObject *type, PyObject *, PyObject *) {
492 const detail::type_info *type_info = capsule(
493 PyObject_GetAttrString((PyObject *) type, const_cast<char*>("__pybind__")), false);
494 instance<void> *self = (instance<void> *) PyType_GenericAlloc(type, 0);
495 self->value = ::operator new(type_info->type_size);
496 self->owned = true;
497 self->parent = nullptr;
498 self->constructed = false;
499 detail::get_internals().registered_instances[self->value] = (PyObject *) self;
500 return (PyObject *) self;
501 }
502
503 static void dealloc(instance<void> *self) {
504 if (self->value) {
505 bool dont_cache = self->parent && ((instance<void> *) self->parent)->value == self->value;
506 if (!dont_cache) { // avoid an issue with internal references matching their parent's address
507 auto &registered_instances = detail::get_internals().registered_instances;
508 auto it = registered_instances.find(self->value);
509 if (it == registered_instances.end())
510 throw std::runtime_error("Deallocating unregistered instance!");
511 registered_instances.erase(it);
512 }
513 Py_XDECREF(self->parent);
514 }
515 Py_TYPE(self)->tp_free((PyObject*) self);
516 }
517
Wenzel Jakob43398a82015-07-28 16:12:20 +0200518 void install_buffer_funcs(
519 buffer_info *(*get_buffer)(PyObject *, void *),
520 void *get_buffer_data) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200521 PyHeapTypeObject *type = (PyHeapTypeObject*) m_ptr;
522 type->ht_type.tp_as_buffer = &type->as_buffer;
523 type->as_buffer.bf_getbuffer = getbuffer;
524 type->as_buffer.bf_releasebuffer = releasebuffer;
Wenzel Jakob43398a82015-07-28 16:12:20 +0200525 auto info = ((detail::type_info *) capsule(attr("__pybind__")));
526 info->get_buffer = get_buffer;
527 info->get_buffer_data = get_buffer_data;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200528 }
529
530 static int getbuffer(PyObject *obj, Py_buffer *view, int flags) {
Wenzel Jakob43398a82015-07-28 16:12:20 +0200531 auto const &typeinfo = ((detail::type_info *) capsule(handle(obj).attr("__pybind__")));
532
533 if (view == nullptr || obj == nullptr || !typeinfo || !typeinfo->get_buffer) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200534 PyErr_SetString(PyExc_BufferError, "Internal error");
535 return -1;
536 }
537 memset(view, 0, sizeof(Py_buffer));
Wenzel Jakob43398a82015-07-28 16:12:20 +0200538 buffer_info *info = typeinfo->get_buffer(obj, typeinfo->get_buffer_data);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200539 view->obj = obj;
540 view->ndim = 1;
541 view->internal = info;
542 view->buf = info->ptr;
543 view->itemsize = info->itemsize;
544 view->len = view->itemsize;
545 for (auto s : info->shape)
546 view->len *= s;
547 if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT)
548 view->format = const_cast<char *>(info->format.c_str());
549 if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
550 view->ndim = info->ndim;
551 view->strides = (Py_ssize_t *)&info->strides[0];
552 view->shape = (Py_ssize_t *) &info->shape[0];
553 }
554 Py_INCREF(view->obj);
555 return 0;
556 }
557
558 static void releasebuffer(PyObject *, Py_buffer *view) { delete (buffer_info *) view->internal; }
559};
Wenzel Jakob71867832015-07-29 17:43:52 +0200560
561/* Forward declarations */
562enum op_id : int;
563enum op_type : int;
564struct undefined_t;
565template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t> struct op_;
566template <typename... Args> struct init;
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200567NAMESPACE_END(detail)
568
569template <typename type, typename holder_type = std::unique_ptr<type>> class class_ : public detail::custom_type {
570public:
571 typedef detail::instance<type, holder_type> instance_type;
572
Wenzel Jakobd4258ba2015-07-26 16:33:49 +0200573 PYBIND_OBJECT(class_, detail::custom_type, PyType_Check)
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200574
575 class_(object &scope, const char *name, const char *doc = nullptr)
576 : detail::custom_type(scope, name, type_id<type>(), sizeof(type),
577 sizeof(instance_type), init_holder, dealloc,
578 nullptr, doc) { }
579
580 class_(object &scope, const char *name, object &parent,
581 const char *doc = nullptr)
582 : detail::custom_type(scope, name, type_id<type>(), sizeof(type),
583 sizeof(instance_type), init_holder, dealloc,
584 parent.ptr(), doc) { }
585
Wenzel Jakob71867832015-07-29 17:43:52 +0200586 template <typename Func, typename... Extra>
587 class_ &def(const char *name_, Func&& f, Extra&&... extra) {
588 attr(name_) = cpp_function(std::forward<Func>(f), name(name_),
589 sibling(attr(name_)), is_method(),
590 std::forward<Extra>(extra)...);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200591 return *this;
592 }
593
Wenzel Jakob71867832015-07-29 17:43:52 +0200594 template <typename Func, typename... Extra> class_ &
595 def_static(const char *name_, Func f, Extra&&... extra) {
596 attr(name_) = cpp_function(std::forward<Func>(f), name(name_),
597 sibling(attr(name_)),
598 std::forward<Extra>(extra)...);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200599 return *this;
600 }
601
Wenzel Jakob71867832015-07-29 17:43:52 +0200602 template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
603 class_ &def(const detail::op_<id, ot, L, R> &op, Extra&&... extra) {
604 op.template execute<type>(*this, std::forward<Extra>(extra)...);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200605 return *this;
606 }
607
Wenzel Jakob71867832015-07-29 17:43:52 +0200608 template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
609 class_ & def_cast(const detail::op_<id, ot, L, R> &op, Extra&&... extra) {
610 op.template execute_cast<type>(*this, std::forward<Extra>(extra)...);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200611 return *this;
612 }
613
Wenzel Jakob71867832015-07-29 17:43:52 +0200614 template <typename... Args, typename... Extra>
615 class_ &def(const detail::init<Args...> &init, Extra&&... extra) {
616 init.template execute<type>(*this, std::forward<Extra>(extra)...);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200617 return *this;
618 }
619
Wenzel Jakob71867832015-07-29 17:43:52 +0200620 template <typename Func> class_& def_buffer(Func &&func) {
Wenzel Jakob43398a82015-07-28 16:12:20 +0200621 struct capture { Func func; };
622 capture *ptr = new capture { std::forward<Func>(func) };
623 install_buffer_funcs([](PyObject *obj, void *ptr) -> buffer_info* {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200624 detail::type_caster<type> caster;
625 if (!caster.load(obj, false))
626 return nullptr;
Wenzel Jakob43398a82015-07-28 16:12:20 +0200627 return new buffer_info(((capture *) ptr)->func(caster));
628 }, ptr);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200629 return *this;
630 }
631
Wenzel Jakob71867832015-07-29 17:43:52 +0200632 template <typename C, typename D, typename... Extra>
633 class_ &def_readwrite(const char *name, D C::*pm, Extra&&... extra) {
634 cpp_function fget([pm](const C &c) -> const D &{ return c.*pm; },
635 return_value_policy::reference_internal,
636 is_method(), extra...),
637 fset([pm](C &c, const D &value) { c.*pm = value; },
638 is_method(), extra...);
639 def_property(name, fget, fset);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200640 return *this;
641 }
642
Wenzel Jakob71867832015-07-29 17:43:52 +0200643 template <typename C, typename D, typename... Extra>
644 class_ &def_readonly(const char *name, const D C::*pm, Extra&& ...extra) {
645 cpp_function fget([pm](const C &c) -> const D &{ return c.*pm; },
646 return_value_policy::reference_internal,
647 is_method(), std::forward<Extra>(extra)...);
648 def_property_readonly(name, fget);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200649 return *this;
650 }
651
Wenzel Jakob71867832015-07-29 17:43:52 +0200652 template <typename D, typename... Extra>
653 class_ &def_readwrite_static(const char *name, D *pm, Extra&& ...extra) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200654 cpp_function fget([pm](object) -> const D &{ return *pm; }, nullptr,
Wenzel Jakob71867832015-07-29 17:43:52 +0200655 return_value_policy::reference_internal, extra...),
656 fset([pm](object, const D &value) { *pm = value; }, extra...);
657 def_property_static(name, fget, fset);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200658 return *this;
659 }
660
Wenzel Jakob71867832015-07-29 17:43:52 +0200661 template <typename D, typename... Extra>
662 class_ &def_readonly_static(const char *name, const D *pm, Extra&& ...extra) {
Wenzel Jakobbd4a5292015-07-11 17:41:48 +0200663 cpp_function fget([pm](object) -> const D &{ return *pm; }, nullptr,
Wenzel Jakob71867832015-07-29 17:43:52 +0200664 return_value_policy::reference_internal, std::forward<Extra>(extra)...);
665 def_property_readonly_static(name, fget);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200666 return *this;
667 }
668
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200669 class_ &def_property_readonly(const char *name, const cpp_function &fget, const char *doc = nullptr) {
670 def_property(name, fget, cpp_function(), doc);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200671 return *this;
672 }
673
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200674 class_ &def_property_readonly_static(const char *name, const cpp_function &fget, const char *doc = nullptr) {
675 def_property_static(name, fget, cpp_function(), doc);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200676 return *this;
677 }
678
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200679 class_ &def_property(const char *name, const cpp_function &fget, const cpp_function &fset, const char *doc = nullptr) {
680 object doc_obj = doc ? pybind::str(doc) : (object) const_cast<cpp_function&>(fget).attr("__doc__");
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200681 object property(
682 PyObject_CallFunction((PyObject *)&PyProperty_Type,
Wenzel Jakob71867832015-07-29 17:43:52 +0200683 const_cast<char *>("OOOO"), fget.ptr() ? fget.ptr() : Py_None,
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200684 fset.ptr() ? fset.ptr() : Py_None, Py_None, doc_obj.ptr()), false);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200685 attr(name) = property;
686 return *this;
687 }
688
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200689 class_ &def_property_static(const char *name, const cpp_function &fget, const cpp_function &fset, const char *doc = nullptr) {
690 object doc_obj = doc ? pybind::str(doc) : (object) const_cast<cpp_function&>(fget).attr("__doc__");
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200691 object property(
692 PyObject_CallFunction((PyObject *)&PyProperty_Type,
Wenzel Jakoba576e6a2015-07-29 17:51:54 +0200693 const_cast<char *>("OOOs"), fget.ptr() ? fget.ptr() : Py_None,
694 fset.ptr() ? fset.ptr() : Py_None, Py_None, doc_obj.ptr()), false);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200695 metaclass().attr(name) = property;
696 return *this;
697 }
698private:
699 static void init_holder(PyObject *inst_) {
700 instance_type *inst = (instance_type *) inst_;
701 new (&inst->holder) holder_type(inst->value);
702 inst->constructed = true;
703 }
704 static void dealloc(PyObject *inst_) {
705 instance_type *inst = (instance_type *) inst_;
706 if (inst->owned) {
707 if (inst->constructed)
708 inst->holder.~holder_type();
709 else
710 ::operator delete(inst->value);
711 }
712 custom_type::dealloc((detail::instance<void> *) inst);
713 }
714};
715
716/// Binds C++ enumerations and enumeration classes to Python
717template <typename Type> class enum_ : public class_<Type> {
718public:
719 enum_(object &scope, const char *name, const char *doc = nullptr)
720 : class_<Type>(scope, name, doc), m_parent(scope) {
721 auto entries = new std::unordered_map<int, const char *>();
722 this->def("__str__", [name, entries](Type value) -> std::string {
723 auto it = entries->find(value);
724 return std::string(name) + "." +
725 ((it == entries->end()) ? std::string("???")
726 : std::string(it->second));
727 });
728 m_entries = entries;
729 }
730
731 /// Export enumeration entries into the parent scope
732 void export_values() {
733 PyObject *dict = ((PyTypeObject *) this->m_ptr)->tp_dict;
734 PyObject *key, *value;
735 Py_ssize_t pos = 0;
736 while (PyDict_Next(dict, &pos, &key, &value))
737 if (PyObject_IsInstance(value, this->m_ptr))
738 m_parent.attr(key) = value;
739 }
740
741 /// Add an enumeration entry
742 enum_& value(char const* name, Type value) {
743 this->attr(name) = pybind::cast(value, return_value_policy::copy);
744 (*m_entries)[(int) value] = name;
745 return *this;
746 }
747private:
748 std::unordered_map<int, const char *> *m_entries;
749 object &m_parent;
750};
751
752NAMESPACE_BEGIN(detail)
Wenzel Jakob71867832015-07-29 17:43:52 +0200753template <typename... Args> struct init {
754 template <typename Base, typename Holder, typename... Extra> void execute(pybind::class_<Base, Holder> &class_, Extra&&... extra) const {
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200755 /// Function which calls a specific C++ in-place constructor
Wenzel Jakob71867832015-07-29 17:43:52 +0200756 class_.def("__init__", [](Base *instance, Args... args) { new (instance) Base(args...); }, std::forward<Extra>(extra)...);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200757 }
758};
759NAMESPACE_END(detail)
760
761template <typename... Args> detail::init<Args...> init() { return detail::init<Args...>(); };
762
763template <typename InputType, typename OutputType> void implicitly_convertible() {
764 auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject *{
765 if (!detail::type_caster<InputType>().load(obj, false))
766 return nullptr;
767 tuple args(1);
768 args[0] = obj;
769 PyObject *result = PyObject_Call((PyObject *) type, args.ptr(), nullptr);
770 if (result == nullptr)
771 PyErr_Clear();
772 return result;
773 };
774 std::string output_type_name = type_id<OutputType>();
775 auto & registered_types = detail::get_internals().registered_types;
776 auto it = registered_types.find(output_type_name);
777 if (it == registered_types.end())
778 throw std::runtime_error("implicitly_convertible: Unable to find type " + output_type_name);
779 it->second.implicit_conversions.push_back(implicit_caster);
780}
781
782inline void init_threading() { PyEval_InitThreads(); }
783
784class gil_scoped_acquire {
785 PyGILState_STATE state;
786public:
787 inline gil_scoped_acquire() { state = PyGILState_Ensure(); }
788 inline ~gil_scoped_acquire() { PyGILState_Release(state); }
789};
790
791class gil_scoped_release {
792 PyThreadState *state;
793public:
794 inline gil_scoped_release() { state = PyEval_SaveThread(); }
795 inline ~gil_scoped_release() { PyEval_RestoreThread(state); }
796};
797
798NAMESPACE_END(pybind)
799
800#if defined(_MSC_VER)
801#pragma warning(pop)
802#endif