1 /*
2     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
3 
4     All rights reserved. Use of this source code is governed by a
5     BSD-style license that can be found in the LICENSE file.
6 */
7 
8 
9 
10 
11 #pragma once
12 
13 #include "../attr.h"
14 
15 NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
NAMESPACE_BEGIN(detail)16 NAMESPACE_BEGIN(detail)
17 
18 #if PY_VERSION_HEX >= 0x03030000
19 #  define PYBIND11_BUILTIN_QUALNAME
20 #  define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj)
21 #else
22 
23 
24 #  define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj) setattr((PyObject *) obj, "__qualname__", nameobj)
25 #endif
26 
27 inline PyTypeObject *type_incref(PyTypeObject *type) {
28     Py_INCREF(type);
29     return type;
30 }
31 
32 #if !defined(PYPY_VERSION)
33 
34 
pybind11_static_get(PyObject * self,PyObject *,PyObject * cls)35 extern "C" inline PyObject *pybind11_static_get(PyObject *self, PyObject *  , PyObject *cls) {
36     return PyProperty_Type.tp_descr_get(self, cls, cls);
37 }
38 
39 
pybind11_static_set(PyObject * self,PyObject * obj,PyObject * value)40 extern "C" inline int pybind11_static_set(PyObject *self, PyObject *obj, PyObject *value) {
41     PyObject *cls = PyType_Check(obj) ? obj : (PyObject *) Py_TYPE(obj);
42     return PyProperty_Type.tp_descr_set(self, cls, value);
43 }
44 
45 
make_static_property_type()46 inline PyTypeObject *make_static_property_type() {
47     constexpr auto *name = "pybind11_static_property";
48     auto name_obj = reinterpret_steal<object>(PYBIND11_FROM_STRING(name));
49 
50 
51     auto heap_type = (PyHeapTypeObject *) PyType_Type.tp_alloc(&PyType_Type, 0);
52     if (!heap_type)
53         pybind11_fail("make_static_property_type(): error allocating type!");
54 
55     heap_type->ht_name = name_obj.inc_ref().ptr();
56 #ifdef PYBIND11_BUILTIN_QUALNAME
57     heap_type->ht_qualname = name_obj.inc_ref().ptr();
58 #endif
59 
60     auto type = &heap_type->ht_type;
61     type->tp_name = name;
62     type->tp_base = type_incref(&PyProperty_Type);
63     type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
64     type->tp_descr_get = pybind11_static_get;
65     type->tp_descr_set = pybind11_static_set;
66 
67     if (PyType_Ready(type) < 0)
68         pybind11_fail("make_static_property_type(): failure in PyType_Ready()!");
69 
70     setattr((PyObject *) type, "__module__", str("pybind11_builtins"));
71     PYBIND11_SET_OLDPY_QUALNAME(type, name_obj);
72 
73     return type;
74 }
75 
76 #else
77 
78 
make_static_property_type()79 inline PyTypeObject *make_static_property_type() {
80     auto d = dict();
81     PyObject *result = PyRun_String(R"(\
82         class pybind11_static_property(property):
83             def __get__(self, obj, cls):
84                 return property.__get__(self, cls, cls)
85 
86             def __set__(self, obj, value):
87                 cls = obj if isinstance(obj, type) else type(obj)
88                 property.__set__(self, cls, value)
89         )", Py_file_input, d.ptr(), d.ptr()
90     );
91     if (result == nullptr)
92         throw error_already_set();
93     Py_DECREF(result);
94     return (PyTypeObject *) d["pybind11_static_property"].cast<object>().release().ptr();
95 }
96 
97 #endif
98 
99 
pybind11_meta_setattro(PyObject * obj,PyObject * name,PyObject * value)100 extern "C" inline int pybind11_meta_setattro(PyObject* obj, PyObject* name, PyObject* value) {
101 
102 
103     PyObject *descr = _PyType_Lookup((PyTypeObject *) obj, name);
104 
105 
106 
107 
108 
109     const auto static_prop = (PyObject *) get_internals().static_property_type;
110     const auto call_descr_set = descr && PyObject_IsInstance(descr, static_prop)
111                                 && !PyObject_IsInstance(value, static_prop);
112     if (call_descr_set) {
113 
114 #if !defined(PYPY_VERSION)
115         return Py_TYPE(descr)->tp_descr_set(descr, obj, value);
116 #else
117         if (PyObject *result = PyObject_CallMethod(descr, "__set__", "OO", obj, value)) {
118             Py_DECREF(result);
119             return 0;
120         } else {
121             return -1;
122         }
123 #endif
124     } else {
125 
126         return PyType_Type.tp_setattro(obj, name, value);
127     }
128 }
129 
130 #if PY_MAJOR_VERSION >= 3
131 
pybind11_meta_getattro(PyObject * obj,PyObject * name)132 extern "C" inline PyObject *pybind11_meta_getattro(PyObject *obj, PyObject *name) {
133     PyObject *descr = _PyType_Lookup((PyTypeObject *) obj, name);
134     if (descr && PyInstanceMethod_Check(descr)) {
135         Py_INCREF(descr);
136         return descr;
137     }
138     else {
139         return PyType_Type.tp_getattro(obj, name);
140     }
141 }
142 #endif
143 
144 
make_default_metaclass()145 inline PyTypeObject* make_default_metaclass() {
146     constexpr auto *name = "pybind11_type";
147     auto name_obj = reinterpret_steal<object>(PYBIND11_FROM_STRING(name));
148 
149 
150     auto heap_type = (PyHeapTypeObject *) PyType_Type.tp_alloc(&PyType_Type, 0);
151     if (!heap_type)
152         pybind11_fail("make_default_metaclass(): error allocating metaclass!");
153 
154     heap_type->ht_name = name_obj.inc_ref().ptr();
155 #ifdef PYBIND11_BUILTIN_QUALNAME
156     heap_type->ht_qualname = name_obj.inc_ref().ptr();
157 #endif
158 
159     auto type = &heap_type->ht_type;
160     type->tp_name = name;
161     type->tp_base = type_incref(&PyType_Type);
162     type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
163 
164     type->tp_setattro = pybind11_meta_setattro;
165 #if PY_MAJOR_VERSION >= 3
166     type->tp_getattro = pybind11_meta_getattro;
167 #endif
168 
169     if (PyType_Ready(type) < 0)
170         pybind11_fail("make_default_metaclass(): failure in PyType_Ready()!");
171 
172     setattr((PyObject *) type, "__module__", str("pybind11_builtins"));
173     PYBIND11_SET_OLDPY_QUALNAME(type, name_obj);
174 
175     return type;
176 }
177 
178 
179 
180 
traverse_offset_bases(void * valueptr,const detail::type_info * tinfo,instance * self,bool (* f)(void *,instance *))181 inline void traverse_offset_bases(void *valueptr, const detail::type_info *tinfo, instance *self,
182         bool (*f)(void *  , instance *  )) {
183     for (handle h : reinterpret_borrow<tuple>(tinfo->type->tp_bases)) {
184         if (auto parent_tinfo = get_type_info((PyTypeObject *) h.ptr())) {
185             for (auto &c : parent_tinfo->implicit_casts) {
186                 if (c.first == tinfo->cpptype) {
187                     auto *parentptr = c.second(valueptr);
188                     if (parentptr != valueptr)
189                         f(parentptr, self);
190                     traverse_offset_bases(parentptr, parent_tinfo, self, f);
191                     break;
192                 }
193             }
194         }
195     }
196 }
197 
register_instance_impl(void * ptr,instance * self)198 inline bool register_instance_impl(void *ptr, instance *self) {
199     get_internals().registered_instances.emplace(ptr, self);
200     return true;
201 }
deregister_instance_impl(void * ptr,instance * self)202 inline bool deregister_instance_impl(void *ptr, instance *self) {
203     auto &registered_instances = get_internals().registered_instances;
204     auto range = registered_instances.equal_range(ptr);
205     for (auto it = range.first; it != range.second; ++it) {
206         if (Py_TYPE(self) == Py_TYPE(it->second)) {
207             registered_instances.erase(it);
208             return true;
209         }
210     }
211     return false;
212 }
213 
register_instance(instance * self,void * valptr,const type_info * tinfo)214 inline void register_instance(instance *self, void *valptr, const type_info *tinfo) {
215     register_instance_impl(valptr, self);
216     if (!tinfo->simple_ancestors)
217         traverse_offset_bases(valptr, tinfo, self, register_instance_impl);
218 }
219 
deregister_instance(instance * self,void * valptr,const type_info * tinfo)220 inline bool deregister_instance(instance *self, void *valptr, const type_info *tinfo) {
221     bool ret = deregister_instance_impl(valptr, self);
222     if (!tinfo->simple_ancestors)
223         traverse_offset_bases(valptr, tinfo, self, deregister_instance_impl);
224     return ret;
225 }
226 
227 
228 
229 
make_new_instance(PyTypeObject * type)230 inline PyObject *make_new_instance(PyTypeObject *type) {
231 #if defined(PYPY_VERSION)
232 
233 
234     ssize_t instance_size = static_cast<ssize_t>(sizeof(instance));
235     if (type->tp_basicsize < instance_size) {
236         type->tp_basicsize = instance_size;
237     }
238 #endif
239     PyObject *self = type->tp_alloc(type, 0);
240     auto inst = reinterpret_cast<instance *>(self);
241 
242     inst->allocate_layout();
243 
244     inst->owned = true;
245 
246     return self;
247 }
248 
249 
250 
pybind11_object_new(PyTypeObject * type,PyObject *,PyObject *)251 extern "C" inline PyObject *pybind11_object_new(PyTypeObject *type, PyObject *, PyObject *) {
252     return make_new_instance(type);
253 }
254 
255 
256 
257 
pybind11_object_init(PyObject * self,PyObject *,PyObject *)258 extern "C" inline int pybind11_object_init(PyObject *self, PyObject *, PyObject *) {
259     PyTypeObject *type = Py_TYPE(self);
260     std::string msg;
261 #if defined(PYPY_VERSION)
262     msg += handle((PyObject *) type).attr("__module__").cast<std::string>() + ".";
263 #endif
264     msg += type->tp_name;
265     msg += ": No constructor defined!";
266     PyErr_SetString(PyExc_TypeError, msg.c_str());
267     return -1;
268 }
269 
add_patient(PyObject * nurse,PyObject * patient)270 inline void add_patient(PyObject *nurse, PyObject *patient) {
271     auto &internals = get_internals();
272     auto instance = reinterpret_cast<detail::instance *>(nurse);
273     instance->has_patients = true;
274     Py_INCREF(patient);
275     internals.patients[nurse].push_back(patient);
276 }
277 
clear_patients(PyObject * self)278 inline void clear_patients(PyObject *self) {
279     auto instance = reinterpret_cast<detail::instance *>(self);
280     auto &internals = get_internals();
281     auto pos = internals.patients.find(self);
282     assert(pos != internals.patients.end());
283 
284 
285 
286     auto patients = std::move(pos->second);
287     internals.patients.erase(pos);
288     instance->has_patients = false;
289     for (PyObject *&patient : patients)
290         Py_CLEAR(patient);
291 }
292 
293 
294 
clear_instance(PyObject * self)295 inline void clear_instance(PyObject *self) {
296     auto instance = reinterpret_cast<detail::instance *>(self);
297 
298 
299     for (auto &v_h : values_and_holders(instance)) {
300         if (v_h) {
301 
302 
303 
304             if (v_h.instance_registered() && !deregister_instance(instance, v_h.value_ptr(), v_h.type))
305                 pybind11_fail("pybind11_object_dealloc(): Tried to deallocate unregistered instance!");
306 
307             if (instance->owned || v_h.holder_constructed())
308                 v_h.type->dealloc(v_h);
309         }
310     }
311 
312     instance->deallocate_layout();
313 
314     if (instance->weakrefs)
315         PyObject_ClearWeakRefs(self);
316 
317     PyObject **dict_ptr = _PyObject_GetDictPtr(self);
318     if (dict_ptr)
319         Py_CLEAR(*dict_ptr);
320 
321     if (instance->has_patients)
322         clear_patients(self);
323 }
324 
325 
326 
pybind11_object_dealloc(PyObject * self)327 extern "C" inline void pybind11_object_dealloc(PyObject *self) {
328     clear_instance(self);
329 
330     auto type = Py_TYPE(self);
331     type->tp_free(self);
332 
333 
334 
335 
336 
337     auto pybind11_object_type = (PyTypeObject *) get_internals().instance_base;
338     if (type->tp_dealloc == pybind11_object_type->tp_dealloc)
339         Py_DECREF(type);
340 }
341 
342 
make_object_base_type(PyTypeObject * metaclass)343 inline PyObject *make_object_base_type(PyTypeObject *metaclass) {
344     constexpr auto *name = "pybind11_object";
345     auto name_obj = reinterpret_steal<object>(PYBIND11_FROM_STRING(name));
346 
347 
348     auto heap_type = (PyHeapTypeObject *) metaclass->tp_alloc(metaclass, 0);
349     if (!heap_type)
350         pybind11_fail("make_object_base_type(): error allocating type!");
351 
352     heap_type->ht_name = name_obj.inc_ref().ptr();
353 #ifdef PYBIND11_BUILTIN_QUALNAME
354     heap_type->ht_qualname = name_obj.inc_ref().ptr();
355 #endif
356 
357     auto type = &heap_type->ht_type;
358     type->tp_name = name;
359     type->tp_base = type_incref(&PyBaseObject_Type);
360     type->tp_basicsize = static_cast<ssize_t>(sizeof(instance));
361     type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
362 
363     type->tp_new = pybind11_object_new;
364     type->tp_init = pybind11_object_init;
365     type->tp_dealloc = pybind11_object_dealloc;
366 
367 
368     type->tp_weaklistoffset = offsetof(instance, weakrefs);
369 
370     if (PyType_Ready(type) < 0)
371         pybind11_fail("PyType_Ready failed in make_object_base_type():" + error_string());
372 
373     setattr((PyObject *) type, "__module__", str("pybind11_builtins"));
374     PYBIND11_SET_OLDPY_QUALNAME(type, name_obj);
375 
376     assert(!PyType_HasFeature(type, Py_TPFLAGS_HAVE_GC));
377     return (PyObject *) heap_type;
378 }
379 
380 
pybind11_get_dict(PyObject * self,void *)381 extern "C" inline PyObject *pybind11_get_dict(PyObject *self, void *) {
382     PyObject *&dict = *_PyObject_GetDictPtr(self);
383     if (!dict)
384         dict = PyDict_New();
385     Py_XINCREF(dict);
386     return dict;
387 }
388 
389 
pybind11_set_dict(PyObject * self,PyObject * new_dict,void *)390 extern "C" inline int pybind11_set_dict(PyObject *self, PyObject *new_dict, void *) {
391     if (!PyDict_Check(new_dict)) {
392         PyErr_Format(PyExc_TypeError, "__dict__ must be set to a dictionary, not a '%.200s'",
393                      Py_TYPE(new_dict)->tp_name);
394         return -1;
395     }
396     PyObject *&dict = *_PyObject_GetDictPtr(self);
397     Py_INCREF(new_dict);
398     Py_CLEAR(dict);
399     dict = new_dict;
400     return 0;
401 }
402 
403 
pybind11_traverse(PyObject * self,visitproc visit,void * arg)404 extern "C" inline int pybind11_traverse(PyObject *self, visitproc visit, void *arg) {
405     PyObject *&dict = *_PyObject_GetDictPtr(self);
406     Py_VISIT(dict);
407     return 0;
408 }
409 
410 
pybind11_clear(PyObject * self)411 extern "C" inline int pybind11_clear(PyObject *self) {
412     PyObject *&dict = *_PyObject_GetDictPtr(self);
413     Py_CLEAR(dict);
414     return 0;
415 }
416 
417 
enable_dynamic_attributes(PyHeapTypeObject * heap_type)418 inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) {
419     auto type = &heap_type->ht_type;
420 #if defined(PYPY_VERSION)
421     pybind11_fail(std::string(type->tp_name) + ": dynamic attributes are "
422                                                "currently not supported in "
423                                                "conjunction with PyPy!");
424 #endif
425     type->tp_flags |= Py_TPFLAGS_HAVE_GC;
426     type->tp_dictoffset = type->tp_basicsize;
427     type->tp_basicsize += (ssize_t)sizeof(PyObject *);
428     type->tp_traverse = pybind11_traverse;
429     type->tp_clear = pybind11_clear;
430 
431     static PyGetSetDef getset[] = {
432         {const_cast<char*>("__dict__"), pybind11_get_dict, pybind11_set_dict, nullptr, nullptr},
433         {nullptr, nullptr, nullptr, nullptr, nullptr}
434     };
435     type->tp_getset = getset;
436 }
437 
438 
pybind11_getbuffer(PyObject * obj,Py_buffer * view,int flags)439 extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int flags) {
440 
441     type_info *tinfo = nullptr;
442     for (auto type : reinterpret_borrow<tuple>(Py_TYPE(obj)->tp_mro)) {
443         tinfo = get_type_info((PyTypeObject *) type.ptr());
444         if (tinfo && tinfo->get_buffer)
445             break;
446     }
447     if (view == nullptr || obj == nullptr || !tinfo || !tinfo->get_buffer) {
448         if (view)
449             view->obj = nullptr;
450         PyErr_SetString(PyExc_BufferError, "pybind11_getbuffer(): Internal error");
451         return -1;
452     }
453     std::memset(view, 0, sizeof(Py_buffer));
454     buffer_info *info = tinfo->get_buffer(obj, tinfo->get_buffer_data);
455     view->obj = obj;
456     view->ndim = 1;
457     view->internal = info;
458     view->buf = info->ptr;
459     view->itemsize = info->itemsize;
460     view->len = view->itemsize;
461     for (auto s : info->shape)
462         view->len *= s;
463     if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT)
464         view->format = const_cast<char *>(info->format.c_str());
465     if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
466         view->ndim = (int) info->ndim;
467         view->strides = &info->strides[0];
468         view->shape = &info->shape[0];
469     }
470     Py_INCREF(view->obj);
471     return 0;
472 }
473 
474 
pybind11_releasebuffer(PyObject *,Py_buffer * view)475 extern "C" inline void pybind11_releasebuffer(PyObject *, Py_buffer *view) {
476     delete (buffer_info *) view->internal;
477 }
478 
479 
enable_buffer_protocol(PyHeapTypeObject * heap_type)480 inline void enable_buffer_protocol(PyHeapTypeObject *heap_type) {
481     heap_type->ht_type.tp_as_buffer = &heap_type->as_buffer;
482 #if PY_MAJOR_VERSION < 3
483     heap_type->ht_type.tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
484 #endif
485 
486     heap_type->as_buffer.bf_getbuffer = pybind11_getbuffer;
487     heap_type->as_buffer.bf_releasebuffer = pybind11_releasebuffer;
488 }
489 
490 
make_new_python_type(const type_record & rec)491 inline PyObject* make_new_python_type(const type_record &rec) {
492     auto name = reinterpret_steal<object>(PYBIND11_FROM_STRING(rec.name));
493 
494     auto qualname = name;
495     if (rec.scope && !PyModule_Check(rec.scope.ptr()) && hasattr(rec.scope, "__qualname__")) {
496 #if PY_MAJOR_VERSION >= 3
497         qualname = reinterpret_steal<object>(
498             PyUnicode_FromFormat("%U.%U", rec.scope.attr("__qualname__").ptr(), name.ptr()));
499 #else
500         qualname = str(rec.scope.attr("__qualname__").cast<std::string>() + "." + rec.name);
501 #endif
502     }
503 
504     object module;
505     if (rec.scope) {
506         if (hasattr(rec.scope, "__module__"))
507             module = rec.scope.attr("__module__");
508         else if (hasattr(rec.scope, "__name__"))
509             module = rec.scope.attr("__name__");
510     }
511 
512     auto full_name = c_str(
513 #if !defined(PYPY_VERSION)
514         module ? str(module).cast<std::string>() + "." + rec.name :
515 #endif
516         rec.name);
517 
518     char *tp_doc = nullptr;
519     if (rec.doc && options::show_user_defined_docstrings()) {
520 
521         size_t size = strlen(rec.doc) + 1;
522         tp_doc = (char *) PyObject_MALLOC(size);
523         memcpy((void *) tp_doc, rec.doc, size);
524     }
525 
526     auto &internals = get_internals();
527     auto bases = tuple(rec.bases);
528     auto base = (bases.size() == 0) ? internals.instance_base
529                                     : bases[0].ptr();
530 
531 
532     auto metaclass = rec.metaclass.ptr() ? (PyTypeObject *) rec.metaclass.ptr()
533                                          : internals.default_metaclass;
534 
535     auto heap_type = (PyHeapTypeObject *) metaclass->tp_alloc(metaclass, 0);
536     if (!heap_type)
537         pybind11_fail(std::string(rec.name) + ": Unable to create type object!");
538 
539     heap_type->ht_name = name.release().ptr();
540 #ifdef PYBIND11_BUILTIN_QUALNAME
541     heap_type->ht_qualname = qualname.inc_ref().ptr();
542 #endif
543 
544     auto type = &heap_type->ht_type;
545     type->tp_name = full_name;
546     type->tp_doc = tp_doc;
547     type->tp_base = type_incref((PyTypeObject *)base);
548     type->tp_basicsize = static_cast<ssize_t>(sizeof(instance));
549     if (bases.size() > 0)
550         type->tp_bases = bases.release().ptr();
551 
552 
553     type->tp_init = pybind11_object_init;
554 
555 
556     type->tp_as_number = &heap_type->as_number;
557     type->tp_as_sequence = &heap_type->as_sequence;
558     type->tp_as_mapping = &heap_type->as_mapping;
559 
560 
561     type->tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
562 #if PY_MAJOR_VERSION < 3
563     type->tp_flags |= Py_TPFLAGS_CHECKTYPES;
564 #endif
565 
566     if (rec.dynamic_attr)
567         enable_dynamic_attributes(heap_type);
568 
569     if (rec.buffer_protocol)
570         enable_buffer_protocol(heap_type);
571 
572     if (PyType_Ready(type) < 0)
573         pybind11_fail(std::string(rec.name) + ": PyType_Ready failed (" + error_string() + ")!");
574 
575     assert(rec.dynamic_attr ? PyType_HasFeature(type, Py_TPFLAGS_HAVE_GC)
576                             : !PyType_HasFeature(type, Py_TPFLAGS_HAVE_GC));
577 
578 
579     if (rec.scope)
580         setattr(rec.scope, rec.name, (PyObject *) type);
581     else
582         Py_INCREF(type);
583 
584     if (module)
585         setattr((PyObject *) type, "__module__", module);
586 
587     PYBIND11_SET_OLDPY_QUALNAME(type, qualname);
588 
589     return (PyObject *) type;
590 }
591 
592 NAMESPACE_END(detail)
593 NAMESPACE_END(PYBIND11_NAMESPACE)
594