]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/python/src/object/class.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / python / src / object / class.cpp
1 // Copyright David Abrahams 2001.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6 #include <boost/python/detail/prefix.hpp>
7 #include <boost/mpl/lambda.hpp> // #including this first is an intel6 workaround
8
9 #include <boost/python/object/class.hpp>
10 #include <boost/python/object/instance.hpp>
11 #include <boost/python/object/class_detail.hpp>
12 #include <boost/python/scope.hpp>
13 #include <boost/python/converter/registry.hpp>
14 #include <boost/python/object/find_instance.hpp>
15 #include <boost/python/object/pickle_support.hpp>
16 #include <boost/python/detail/map_entry.hpp>
17 #include <boost/python/object.hpp>
18 #include <boost/python/object_protocol.hpp>
19 #include <boost/detail/binary_search.hpp>
20 #include <boost/python/self.hpp>
21 #include <boost/python/dict.hpp>
22 #include <boost/python/str.hpp>
23 #include <boost/python/ssize_t.hpp>
24 #include <functional>
25 #include <vector>
26 #include <cstddef>
27 #include <new>
28 #include <structmember.h>
29
30 namespace boost { namespace python {
31
32 # ifdef BOOST_PYTHON_SELF_IS_CLASS
33 namespace self_ns
34 {
35 self_t self;
36 }
37 # endif
38
39 instance_holder::instance_holder()
40 : m_next(0)
41 {
42 }
43
44 instance_holder::~instance_holder()
45 {
46 }
47
48 extern "C"
49 {
50 // This is copied from typeobject.c in the Python sources. Even though
51 // class_metatype_object doesn't set Py_TPFLAGS_HAVE_GC, that bit gets
52 // filled in by the base class initialization process in
53 // PyType_Ready(). However, tp_is_gc is *not* copied from the base
54 // type, making it assume that classes are GC-able even if (like
55 // class_type_object) they're statically allocated.
56 static int
57 type_is_gc(PyTypeObject *python_type)
58 {
59 return python_type->tp_flags & Py_TPFLAGS_HEAPTYPE;
60 }
61
62 // This is also copied from the Python sources. We can't implement
63 // static_data as a subclass property effectively without it.
64 typedef struct {
65 PyObject_HEAD
66 PyObject *prop_get;
67 PyObject *prop_set;
68 PyObject *prop_del;
69 PyObject *prop_doc;
70 int getter_doc;
71 } propertyobject;
72
73 // Copied from Python source and removed the part for setting docstring,
74 // since we don't have a setter for __doc__ and trying to set it will
75 // cause the init fail.
76 static int property_init(PyObject *self, PyObject *args, PyObject *kwds)
77 {
78 PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
79 static const char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
80 propertyobject *prop = (propertyobject *)self;
81
82 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
83 const_cast<char **>(kwlist), &get, &set, &del, &doc))
84 return -1;
85
86 if (get == Py_None)
87 get = NULL;
88 if (set == Py_None)
89 set = NULL;
90 if (del == Py_None)
91 del = NULL;
92
93 Py_XINCREF(get);
94 Py_XINCREF(set);
95 Py_XINCREF(del);
96 Py_XINCREF(doc);
97
98 prop->prop_get = get;
99 prop->prop_set = set;
100 prop->prop_del = del;
101 prop->prop_doc = doc;
102 prop->getter_doc = 0;
103
104 return 0;
105 }
106
107
108 static PyObject *
109 static_data_descr_get(PyObject *self, PyObject * /*obj*/, PyObject * /*type*/)
110 {
111 propertyobject *gs = (propertyobject *)self;
112
113 return PyObject_CallFunction(gs->prop_get, const_cast<char*>("()"));
114 }
115
116 static int
117 static_data_descr_set(PyObject *self, PyObject * /*obj*/, PyObject *value)
118 {
119 propertyobject *gs = (propertyobject *)self;
120 PyObject *func, *res;
121
122 if (value == NULL)
123 func = gs->prop_del;
124 else
125 func = gs->prop_set;
126 if (func == NULL) {
127 PyErr_SetString(PyExc_AttributeError,
128 value == NULL ?
129 "can't delete attribute" :
130 "can't set attribute");
131 return -1;
132 }
133 if (value == NULL)
134 res = PyObject_CallFunction(func, const_cast<char*>("()"));
135 else
136 res = PyObject_CallFunction(func, const_cast<char*>("(O)"), value);
137 if (res == NULL)
138 return -1;
139 Py_DECREF(res);
140 return 0;
141 }
142 }
143
144 static PyTypeObject static_data_object = {
145 PyVarObject_HEAD_INIT(NULL, 0)
146 const_cast<char*>("Boost.Python.StaticProperty"),
147 sizeof(propertyobject),
148 0,
149 0, /* tp_dealloc */
150 0, /* tp_print */
151 0, /* tp_getattr */
152 0, /* tp_setattr */
153 0, /* tp_compare */
154 0, /* tp_repr */
155 0, /* tp_as_number */
156 0, /* tp_as_sequence */
157 0, /* tp_as_mapping */
158 0, /* tp_hash */
159 0, /* tp_call */
160 0, /* tp_str */
161 0, /* tp_getattro */
162 0, /* tp_setattro */
163 0, /* tp_as_buffer */
164 Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
165 | Py_TPFLAGS_BASETYPE, /* tp_flags */
166 0, /* tp_doc */
167 0, /* tp_traverse */
168 0, /* tp_clear */
169 0, /* tp_richcompare */
170 0, /* tp_weaklistoffset */
171 0, /* tp_iter */
172 0, /* tp_iternext */
173 0, /* tp_methods */
174 0, /* tp_members */
175 0, /* tp_getset */
176 0, //&PyProperty_Type, /* tp_base */
177 0, /* tp_dict */
178 static_data_descr_get, /* tp_descr_get */
179 static_data_descr_set, /* tp_descr_set */
180 0, /* tp_dictoffset */
181 property_init, /* tp_init */
182 0, /* tp_alloc */
183 0, // filled in with type_new /* tp_new */
184 0, // filled in with __PyObject_GC_Del /* tp_free */
185 0, /* tp_is_gc */
186 0, /* tp_bases */
187 0, /* tp_mro */
188 0, /* tp_cache */
189 0, /* tp_subclasses */
190 0, /* tp_weaklist */
191 #if PYTHON_API_VERSION >= 1012
192 0 /* tp_del */
193 #endif
194 };
195
196 namespace objects
197 {
198 #if PY_VERSION_HEX < 0x03000000
199 // XXX Not sure why this run into compiling error in Python 3
200 extern "C"
201 {
202 // This declaration needed due to broken Python 2.2 headers
203 extern DL_IMPORT(PyTypeObject) PyProperty_Type;
204 }
205 #endif
206
207 BOOST_PYTHON_DECL PyObject* static_data()
208 {
209 if (static_data_object.tp_dict == 0)
210 {
211 Py_TYPE(&static_data_object) = &PyType_Type;
212 static_data_object.tp_base = &PyProperty_Type;
213 if (PyType_Ready(&static_data_object))
214 return 0;
215 }
216 return upcast<PyObject>(&static_data_object);
217 }
218 }
219
220 extern "C"
221 {
222 // Ordinarily, descriptors have a certain assymetry: you can use
223 // them to read attributes off the class object they adorn, but
224 // writing the same attribute on the class object always replaces
225 // the descriptor in the class __dict__. In order to properly
226 // represent C++ static data members, we need to allow them to be
227 // written through the class instance. This function of the
228 // metaclass makes it possible.
229 static int
230 class_setattro(PyObject *obj, PyObject *name, PyObject* value)
231 {
232 // Must use "private" Python implementation detail
233 // _PyType_Lookup instead of PyObject_GetAttr because the
234 // latter will always end up calling the descr_get function on
235 // any descriptor it finds; we need the unadulterated
236 // descriptor here.
237 PyObject* a = _PyType_Lookup(downcast<PyTypeObject>(obj), name);
238
239 // a is a borrowed reference or 0
240
241 // If we found a static data descriptor, call it directly to
242 // force it to set the static data member
243 if (a != 0 && PyObject_IsInstance(a, objects::static_data()))
244 return Py_TYPE(a)->tp_descr_set(a, obj, value);
245 else
246 return PyType_Type.tp_setattro(obj, name, value);
247 }
248 }
249
250 static PyTypeObject class_metatype_object = {
251 PyVarObject_HEAD_INIT(NULL, 0)
252 const_cast<char*>("Boost.Python.class"),
253 PyType_Type.tp_basicsize,
254 0,
255 0, /* tp_dealloc */
256 0, /* tp_print */
257 0, /* tp_getattr */
258 0, /* tp_setattr */
259 0, /* tp_compare */
260 0, /* tp_repr */
261 0, /* tp_as_number */
262 0, /* tp_as_sequence */
263 0, /* tp_as_mapping */
264 0, /* tp_hash */
265 0, /* tp_call */
266 0, /* tp_str */
267 0, /* tp_getattro */
268 class_setattro, /* tp_setattro */
269 0, /* tp_as_buffer */
270 Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
271 | Py_TPFLAGS_BASETYPE, /* tp_flags */
272 0, /* tp_doc */
273 0, /* tp_traverse */
274 0, /* tp_clear */
275 0, /* tp_richcompare */
276 0, /* tp_weaklistoffset */
277 0, /* tp_iter */
278 0, /* tp_iternext */
279 0, /* tp_methods */
280 0, /* tp_members */
281 0, /* tp_getset */
282 0, //&PyType_Type, /* tp_base */
283 0, /* tp_dict */
284 0, /* tp_descr_get */
285 0, /* tp_descr_set */
286 0, /* tp_dictoffset */
287 0, /* tp_init */
288 0, /* tp_alloc */
289 0, // filled in with type_new /* tp_new */
290 0, // filled in with __PyObject_GC_Del /* tp_free */
291 (inquiry)type_is_gc, /* tp_is_gc */
292 0, /* tp_bases */
293 0, /* tp_mro */
294 0, /* tp_cache */
295 0, /* tp_subclasses */
296 0, /* tp_weaklist */
297 #if PYTHON_API_VERSION >= 1012
298 0 /* tp_del */
299 #endif
300 };
301
302 // Install the instance data for a C++ object into a Python instance
303 // object.
304 void instance_holder::install(PyObject* self) throw()
305 {
306 assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self)), &class_metatype_object));
307 m_next = ((objects::instance<>*)self)->objects;
308 ((objects::instance<>*)self)->objects = this;
309 }
310
311
312 namespace objects
313 {
314 // Get the metatype object for all extension classes.
315 BOOST_PYTHON_DECL type_handle class_metatype()
316 {
317 if (class_metatype_object.tp_dict == 0)
318 {
319 Py_TYPE(&class_metatype_object) = &PyType_Type;
320 class_metatype_object.tp_base = &PyType_Type;
321 if (PyType_Ready(&class_metatype_object))
322 return type_handle();
323 }
324 return type_handle(borrowed(&class_metatype_object));
325 }
326 extern "C"
327 {
328 static void instance_dealloc(PyObject* inst)
329 {
330 instance<>* kill_me = (instance<>*)inst;
331
332 for (instance_holder* p = kill_me->objects, *next; p != 0; p = next)
333 {
334 next = p->next();
335 p->~instance_holder();
336 instance_holder::deallocate(inst, dynamic_cast<void*>(p));
337 }
338
339 // Python 2.2.1 won't add weak references automatically when
340 // tp_itemsize > 0, so we need to manage that
341 // ourselves. Accordingly, we also have to clean up the
342 // weakrefs ourselves.
343 if (kill_me->weakrefs != NULL)
344 PyObject_ClearWeakRefs(inst);
345
346 Py_XDECREF(kill_me->dict);
347
348 Py_TYPE(inst)->tp_free(inst);
349 }
350
351 static PyObject *
352 instance_new(PyTypeObject* type_, PyObject* /*args*/, PyObject* /*kw*/)
353 {
354 // Attempt to find the __instance_size__ attribute. If not present, no problem.
355 PyObject* d = type_->tp_dict;
356 PyObject* instance_size_obj = PyObject_GetAttrString(d, const_cast<char*>("__instance_size__"));
357
358 ssize_t instance_size = instance_size_obj ?
359 #if PY_VERSION_HEX >= 0x03000000
360 PyLong_AsSsize_t(instance_size_obj) : 0;
361 #else
362 PyInt_AsLong(instance_size_obj) : 0;
363 #endif
364
365 if (instance_size < 0)
366 instance_size = 0;
367
368 PyErr_Clear(); // Clear any errors that may have occurred.
369
370 instance<>* result = (instance<>*)type_->tp_alloc(type_, instance_size);
371 if (result)
372 {
373 // Guido says we can use ob_size for any purpose we
374 // like, so we'll store the total size of the object
375 // there. A negative number indicates that the extra
376 // instance memory is not yet allocated to any holders.
377 #if PY_VERSION_HEX >= 0x02060000
378 Py_SIZE(result) =
379 #else
380 result->ob_size =
381 #endif
382 -(static_cast<int>(offsetof(instance<>,storage) + instance_size));
383 }
384 return (PyObject*)result;
385 }
386
387 static PyObject* instance_get_dict(PyObject* op, void*)
388 {
389 instance<>* inst = downcast<instance<> >(op);
390 if (inst->dict == 0)
391 inst->dict = PyDict_New();
392 return python::xincref(inst->dict);
393 }
394
395 static int instance_set_dict(PyObject* op, PyObject* dict, void*)
396 {
397 instance<>* inst = downcast<instance<> >(op);
398 python::xdecref(inst->dict);
399 inst->dict = python::incref(dict);
400 return 0;
401 }
402
403 }
404
405
406 static PyGetSetDef instance_getsets[] = {
407 {const_cast<char*>("__dict__"), instance_get_dict, instance_set_dict, NULL, 0},
408 {0, 0, 0, 0, 0}
409 };
410
411
412 static PyMemberDef instance_members[] = {
413 {const_cast<char*>("__weakref__"), T_OBJECT, offsetof(instance<>, weakrefs), 0, 0},
414 {0, 0, 0, 0, 0}
415 };
416
417 static PyTypeObject class_type_object = {
418 PyVarObject_HEAD_INIT(NULL, 0)
419 const_cast<char*>("Boost.Python.instance"),
420 offsetof(instance<>,storage), /* tp_basicsize */
421 1, /* tp_itemsize */
422 instance_dealloc, /* tp_dealloc */
423 0, /* tp_print */
424 0, /* tp_getattr */
425 0, /* tp_setattr */
426 0, /* tp_compare */
427 0, /* tp_repr */
428 0, /* tp_as_number */
429 0, /* tp_as_sequence */
430 0, /* tp_as_mapping */
431 0, /* tp_hash */
432 0, /* tp_call */
433 0, /* tp_str */
434 0, /* tp_getattro */
435 0, /* tp_setattro */
436 0, /* tp_as_buffer */
437 Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
438 | Py_TPFLAGS_BASETYPE, /* tp_flags */
439 0, /* tp_doc */
440 0, /* tp_traverse */
441 0, /* tp_clear */
442 0, /* tp_richcompare */
443 offsetof(instance<>,weakrefs), /* tp_weaklistoffset */
444 0, /* tp_iter */
445 0, /* tp_iternext */
446 0, /* tp_methods */
447 instance_members, /* tp_members */
448 instance_getsets, /* tp_getset */
449 0, //&PyBaseObject_Type, /* tp_base */
450 0, /* tp_dict */
451 0, /* tp_descr_get */
452 0, /* tp_descr_set */
453 offsetof(instance<>,dict), /* tp_dictoffset */
454 0, /* tp_init */
455 PyType_GenericAlloc, /* tp_alloc */
456 instance_new, /* tp_new */
457 0, /* tp_free */
458 0, /* tp_is_gc */
459 0, /* tp_bases */
460 0, /* tp_mro */
461 0, /* tp_cache */
462 0, /* tp_subclasses */
463 0, /* tp_weaklist */
464 #if PYTHON_API_VERSION >= 1012
465 0 /* tp_del */
466 #endif
467 };
468
469 BOOST_PYTHON_DECL type_handle class_type()
470 {
471 if (class_type_object.tp_dict == 0)
472 {
473 Py_TYPE(&class_type_object) = incref(class_metatype().get());
474 class_type_object.tp_base = &PyBaseObject_Type;
475 if (PyType_Ready(&class_type_object))
476 return type_handle();
477 // class_type_object.tp_setattro = class_setattro;
478 }
479 return type_handle(borrowed(&class_type_object));
480 }
481
482 BOOST_PYTHON_DECL void*
483 find_instance_impl(PyObject* inst, type_info type, bool null_shared_ptr_only)
484 {
485 if (!Py_TYPE(Py_TYPE(inst)) ||
486 !PyType_IsSubtype(Py_TYPE(Py_TYPE(inst)), &class_metatype_object))
487 return 0;
488
489 instance<>* self = reinterpret_cast<instance<>*>(inst);
490
491 for (instance_holder* match = self->objects; match != 0; match = match->next())
492 {
493 void* const found = match->holds(type, null_shared_ptr_only);
494 if (found)
495 return found;
496 }
497 return 0;
498 }
499
500 object module_prefix()
501 {
502 return object(
503 PyObject_IsInstance(scope().ptr(), upcast<PyObject>(&PyModule_Type))
504 ? object(scope().attr("__name__"))
505 : api::getattr(scope(), "__module__", str())
506 );
507 }
508
509 namespace
510 {
511 // Find a registered class object corresponding to id. Return a
512 // null handle if no such class is registered.
513 inline type_handle query_class(type_info id)
514 {
515 converter::registration const* p = converter::registry::query(id);
516 return type_handle(
517 python::borrowed(
518 python::allow_null(p ? p->m_class_object : 0))
519 );
520 }
521
522 // Find a registered class corresponding to id. If not found,
523 // throw an appropriate exception.
524 type_handle get_class(type_info id)
525 {
526 type_handle result(query_class(id));
527
528 if (result.get() == 0)
529 {
530 object report("extension class wrapper for base class ");
531 report = report + id.name() + " has not been created yet";
532 PyErr_SetObject(PyExc_RuntimeError, report.ptr());
533 throw_error_already_set();
534 }
535 return result;
536 }
537
538 // class_base constructor
539 //
540 // name - the name of the new Python class
541 //
542 // num_types - one more than the number of declared bases
543 //
544 // types - array of python::type_info, the first item
545 // corresponding to the class being created, and the
546 // rest corresponding to its declared bases.
547 //
548 inline object
549 new_class(char const* name, std::size_t num_types, type_info const* const types, char const* doc)
550 {
551 assert(num_types >= 1);
552
553 // Build a tuple of the base Python type objects. If no bases
554 // were declared, we'll use our class_type() as the single base
555 // class.
556 ssize_t const num_bases = (std::max)(num_types - 1, static_cast<std::size_t>(1));
557 handle<> bases(PyTuple_New(num_bases));
558
559 for (ssize_t i = 1; i <= num_bases; ++i)
560 {
561 type_handle c = (i >= static_cast<ssize_t>(num_types)) ? class_type() : get_class(types[i]);
562 // PyTuple_SET_ITEM steals this reference
563 PyTuple_SET_ITEM(bases.get(), static_cast<ssize_t>(i - 1), upcast<PyObject>(c.release()));
564 }
565
566 // Call the class metatype to create a new class
567 dict d;
568
569 object m = module_prefix();
570 if (m) d["__module__"] = m;
571
572 if (doc != 0)
573 d["__doc__"] = doc;
574
575 object result = object(class_metatype())(name, bases, d);
576 assert(PyType_IsSubtype(Py_TYPE(result.ptr()), &PyType_Type));
577
578 if (scope().ptr() != Py_None)
579 scope().attr(name) = result;
580
581 // For pickle. Will lead to informative error messages if pickling
582 // is not enabled.
583 result.attr("__reduce__") = object(make_instance_reduce_function());
584
585 return result;
586 }
587 }
588
589 class_base::class_base(
590 char const* name, std::size_t num_types, type_info const* const types, char const* doc)
591 : object(new_class(name, num_types, types, doc))
592 {
593 // Insert the new class object in the registry
594 converter::registration& converters = const_cast<converter::registration&>(
595 converter::registry::lookup(types[0]));
596
597 // Class object is leaked, for now
598 converters.m_class_object = (PyTypeObject*)incref(this->ptr());
599 }
600
601 BOOST_PYTHON_DECL void copy_class_object(type_info const& src, type_info const& dst)
602 {
603 converter::registration& dst_converters
604 = const_cast<converter::registration&>(converter::registry::lookup(dst));
605
606 converter::registration const& src_converters = converter::registry::lookup(src);
607
608 dst_converters.m_class_object = src_converters.m_class_object;
609 }
610
611 void class_base::set_instance_size(std::size_t instance_size)
612 {
613 this->attr("__instance_size__") = instance_size;
614 }
615
616 void class_base::add_property(
617 char const* name, object const& fget, char const* docstr)
618 {
619 object property(
620 (python::detail::new_reference)
621 PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("Osss"), fget.ptr(), 0, 0, docstr));
622
623 this->setattr(name, property);
624 }
625
626 void class_base::add_property(
627 char const* name, object const& fget, object const& fset, char const* docstr)
628 {
629 object property(
630 (python::detail::new_reference)
631 PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("OOss"), fget.ptr(), fset.ptr(), 0, docstr));
632
633 this->setattr(name, property);
634 }
635
636 void class_base::add_static_property(char const* name, object const& fget)
637 {
638 object property(
639 (python::detail::new_reference)
640 PyObject_CallFunction(static_data(), const_cast<char*>("O"), fget.ptr())
641 );
642
643 this->setattr(name, property);
644 }
645
646 void class_base::add_static_property(char const* name, object const& fget, object const& fset)
647 {
648 object property(
649 (python::detail::new_reference)
650 PyObject_CallFunction(static_data(), const_cast<char*>("OO"), fget.ptr(), fset.ptr()));
651
652 this->setattr(name, property);
653 }
654
655 void class_base::setattr(char const* name, object const& x)
656 {
657 if (PyObject_SetAttrString(this->ptr(), const_cast<char*>(name), x.ptr()) < 0)
658 throw_error_already_set();
659 }
660
661 namespace
662 {
663 extern "C" PyObject* no_init(PyObject*, PyObject*)
664 {
665 ::PyErr_SetString(::PyExc_RuntimeError, const_cast<char*>("This class cannot be instantiated from Python"));
666 return NULL;
667 }
668 static ::PyMethodDef no_init_def = {
669 const_cast<char*>("__init__"), no_init, METH_VARARGS,
670 const_cast<char*>("Raises an exception\n"
671 "This class cannot be instantiated from Python\n")
672 };
673 }
674
675 void class_base::def_no_init()
676 {
677 handle<> f(::PyCFunction_New(&no_init_def, 0));
678 this->setattr("__init__", object(f));
679 }
680
681 void class_base::enable_pickling_(bool getstate_manages_dict)
682 {
683 setattr("__safe_for_unpickling__", object(true));
684
685 if (getstate_manages_dict)
686 {
687 setattr("__getstate_manages_dict__", object(true));
688 }
689 }
690
691 namespace
692 {
693 PyObject* callable_check(PyObject* callable)
694 {
695 if (PyCallable_Check(expect_non_null(callable)))
696 return callable;
697
698 ::PyErr_Format(
699 PyExc_TypeError
700 , const_cast<char*>("staticmethod expects callable object; got an object of type %s, which is not callable")
701 , Py_TYPE(callable)->tp_name
702 );
703
704 throw_error_already_set();
705 return 0;
706 }
707 }
708
709 void class_base::make_method_static(const char * method_name)
710 {
711 PyTypeObject* self = downcast<PyTypeObject>(this->ptr());
712 dict d((handle<>(borrowed(self->tp_dict))));
713
714 object method(d[method_name]);
715
716 this->attr(method_name) = object(
717 handle<>(
718 PyStaticMethod_New((callable_check)(method.ptr()) )
719 ));
720 }
721
722 BOOST_PYTHON_DECL type_handle registered_class_object(type_info id)
723 {
724 return query_class(id);
725 }
726 } // namespace objects
727
728
729 void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size)
730 {
731 assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object));
732 objects::instance<>* self = (objects::instance<>*)self_;
733
734 int total_size_needed = holder_offset + holder_size;
735
736 if (-Py_SIZE(self) >= total_size_needed)
737 {
738 // holder_offset should at least point into the variable-sized part
739 assert(holder_offset >= offsetof(objects::instance<>,storage));
740
741 // Record the fact that the storage is occupied, noting where it starts
742 Py_SIZE(self) = holder_offset;
743 return (char*)self + holder_offset;
744 }
745 else
746 {
747 void* const result = PyMem_Malloc(holder_size);
748 if (result == 0)
749 throw std::bad_alloc();
750 return result;
751 }
752 }
753
754 void instance_holder::deallocate(PyObject* self_, void* storage) throw()
755 {
756 assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object));
757 objects::instance<>* self = (objects::instance<>*)self_;
758 if (storage != (char*)self + Py_SIZE(self))
759 {
760 PyMem_Free(storage);
761 }
762 }
763
764 }} // namespace boost::python