summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/boost/libs/python/src/object/class.cpp
diff options
context:
space:
mode:
authorneksard <[email protected]>2022-02-10 16:45:33 +0300
committerDaniil Cherednik <[email protected]>2022-02-10 16:45:33 +0300
commit1d9c550e7c38e051d7961f576013a482003a70d9 (patch)
treeb2cc84ee7850122e7ccf51d0ea21e4fa7e7a5685 /contrib/restricted/boost/libs/python/src/object/class.cpp
parent8f7cf138264e0caa318144bf8a2c950e0b0a8593 (diff)
Restoring authorship annotation for <[email protected]>. Commit 2 of 2.
Diffstat (limited to 'contrib/restricted/boost/libs/python/src/object/class.cpp')
-rw-r--r--contrib/restricted/boost/libs/python/src/object/class.cpp1518
1 files changed, 759 insertions, 759 deletions
diff --git a/contrib/restricted/boost/libs/python/src/object/class.cpp b/contrib/restricted/boost/libs/python/src/object/class.cpp
index 63425ce9168..8d0daf63d72 100644
--- a/contrib/restricted/boost/libs/python/src/object/class.cpp
+++ b/contrib/restricted/boost/libs/python/src/object/class.cpp
@@ -1,764 +1,764 @@
-// Copyright David Abrahams 2001.
-// Distributed under the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#include <boost/python/detail/prefix.hpp>
-#include <boost/mpl/lambda.hpp> // #including this first is an intel6 workaround
-
-#include <boost/python/object/class.hpp>
-#include <boost/python/object/instance.hpp>
-#include <boost/python/object/class_detail.hpp>
-#include <boost/python/scope.hpp>
-#include <boost/python/converter/registry.hpp>
-#include <boost/python/object/find_instance.hpp>
-#include <boost/python/object/pickle_support.hpp>
-#include <boost/python/detail/map_entry.hpp>
-#include <boost/python/object.hpp>
-#include <boost/python/object_protocol.hpp>
-#include <boost/detail/binary_search.hpp>
-#include <boost/python/self.hpp>
-#include <boost/python/dict.hpp>
-#include <boost/python/str.hpp>
-#include <boost/python/ssize_t.hpp>
-#include <functional>
-#include <vector>
-#include <cstddef>
-#include <new>
-#include <structmember.h>
-
-namespace boost { namespace python {
-
-# ifdef BOOST_PYTHON_SELF_IS_CLASS
-namespace self_ns
-{
- self_t self;
-}
-# endif
-
-instance_holder::instance_holder()
- : m_next(0)
-{
-}
-
-instance_holder::~instance_holder()
-{
-}
-
-extern "C"
-{
- // This is copied from typeobject.c in the Python sources. Even though
- // class_metatype_object doesn't set Py_TPFLAGS_HAVE_GC, that bit gets
- // filled in by the base class initialization process in
- // PyType_Ready(). However, tp_is_gc is *not* copied from the base
- // type, making it assume that classes are GC-able even if (like
- // class_type_object) they're statically allocated.
- static int
- type_is_gc(PyTypeObject *python_type)
- {
- return python_type->tp_flags & Py_TPFLAGS_HEAPTYPE;
- }
-
- // This is also copied from the Python sources. We can't implement
- // static_data as a subclass property effectively without it.
- typedef struct {
- PyObject_HEAD
- PyObject *prop_get;
- PyObject *prop_set;
- PyObject *prop_del;
- PyObject *prop_doc;
- int getter_doc;
- } propertyobject;
-
- // Copied from Python source and removed the part for setting docstring,
- // since we don't have a setter for __doc__ and trying to set it will
- // cause the init fail.
- static int property_init(PyObject *self, PyObject *args, PyObject *kwds)
- {
- PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
- static const char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
- propertyobject *prop = (propertyobject *)self;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
- const_cast<char **>(kwlist), &get, &set, &del, &doc))
- return -1;
-
- if (get == Py_None)
- get = NULL;
- if (set == Py_None)
- set = NULL;
- if (del == Py_None)
- del = NULL;
-
- Py_XINCREF(get);
- Py_XINCREF(set);
- Py_XINCREF(del);
- Py_XINCREF(doc);
-
- prop->prop_get = get;
- prop->prop_set = set;
- prop->prop_del = del;
- prop->prop_doc = doc;
- prop->getter_doc = 0;
-
- return 0;
- }
-
-
- static PyObject *
- static_data_descr_get(PyObject *self, PyObject * /*obj*/, PyObject * /*type*/)
- {
- propertyobject *gs = (propertyobject *)self;
-
- return PyObject_CallFunction(gs->prop_get, const_cast<char*>("()"));
- }
-
- static int
- static_data_descr_set(PyObject *self, PyObject * /*obj*/, PyObject *value)
- {
- propertyobject *gs = (propertyobject *)self;
- PyObject *func, *res;
-
- if (value == NULL)
- func = gs->prop_del;
- else
- func = gs->prop_set;
- if (func == NULL) {
- PyErr_SetString(PyExc_AttributeError,
- value == NULL ?
- "can't delete attribute" :
- "can't set attribute");
- return -1;
- }
- if (value == NULL)
- res = PyObject_CallFunction(func, const_cast<char*>("()"));
- else
- res = PyObject_CallFunction(func, const_cast<char*>("(O)"), value);
- if (res == NULL)
- return -1;
- Py_DECREF(res);
- return 0;
- }
-}
-
-static PyTypeObject static_data_object = {
- PyVarObject_HEAD_INIT(NULL, 0)
- const_cast<char*>("Boost.Python.StaticProperty"),
- sizeof(propertyobject),
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
- | Py_TPFLAGS_BASETYPE, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, //&PyProperty_Type, /* tp_base */
- 0, /* tp_dict */
- static_data_descr_get, /* tp_descr_get */
- static_data_descr_set, /* tp_descr_set */
- 0, /* tp_dictoffset */
- property_init, /* tp_init */
- 0, /* tp_alloc */
- 0, // filled in with type_new /* tp_new */
- 0, // filled in with __PyObject_GC_Del /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
-#if PYTHON_API_VERSION >= 1012
- 0 /* tp_del */
-#endif
-};
-
-namespace objects
-{
-#if PY_VERSION_HEX < 0x03000000
- // XXX Not sure why this run into compiling error in Python 3
- extern "C"
- {
- // This declaration needed due to broken Python 2.2 headers
- extern DL_IMPORT(PyTypeObject) PyProperty_Type;
- }
-#endif
-
- BOOST_PYTHON_DECL PyObject* static_data()
- {
- if (static_data_object.tp_dict == 0)
- {
- Py_TYPE(&static_data_object) = &PyType_Type;
- static_data_object.tp_base = &PyProperty_Type;
- if (PyType_Ready(&static_data_object))
- return 0;
- }
- return upcast<PyObject>(&static_data_object);
- }
-}
-
-extern "C"
-{
- // Ordinarily, descriptors have a certain assymetry: you can use
- // them to read attributes off the class object they adorn, but
- // writing the same attribute on the class object always replaces
- // the descriptor in the class __dict__. In order to properly
- // represent C++ static data members, we need to allow them to be
- // written through the class instance. This function of the
- // metaclass makes it possible.
- static int
- class_setattro(PyObject *obj, PyObject *name, PyObject* value)
- {
- // Must use "private" Python implementation detail
- // _PyType_Lookup instead of PyObject_GetAttr because the
- // latter will always end up calling the descr_get function on
- // any descriptor it finds; we need the unadulterated
- // descriptor here.
- PyObject* a = _PyType_Lookup(downcast<PyTypeObject>(obj), name);
-
- // a is a borrowed reference or 0
-
- // If we found a static data descriptor, call it directly to
- // force it to set the static data member
- if (a != 0 && PyObject_IsInstance(a, objects::static_data()))
- return Py_TYPE(a)->tp_descr_set(a, obj, value);
- else
- return PyType_Type.tp_setattro(obj, name, value);
- }
-}
-
-static PyTypeObject class_metatype_object = {
- PyVarObject_HEAD_INIT(NULL, 0)
- const_cast<char*>("Boost.Python.class"),
- PyType_Type.tp_basicsize,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- class_setattro, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
- | Py_TPFLAGS_BASETYPE, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, //&PyType_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, // filled in with type_new /* tp_new */
- 0, // filled in with __PyObject_GC_Del /* tp_free */
- (inquiry)type_is_gc, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
-#if PYTHON_API_VERSION >= 1012
- 0 /* tp_del */
-#endif
-};
-
-// Install the instance data for a C++ object into a Python instance
-// object.
+// Copyright David Abrahams 2001.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/python/detail/prefix.hpp>
+#include <boost/mpl/lambda.hpp> // #including this first is an intel6 workaround
+
+#include <boost/python/object/class.hpp>
+#include <boost/python/object/instance.hpp>
+#include <boost/python/object/class_detail.hpp>
+#include <boost/python/scope.hpp>
+#include <boost/python/converter/registry.hpp>
+#include <boost/python/object/find_instance.hpp>
+#include <boost/python/object/pickle_support.hpp>
+#include <boost/python/detail/map_entry.hpp>
+#include <boost/python/object.hpp>
+#include <boost/python/object_protocol.hpp>
+#include <boost/detail/binary_search.hpp>
+#include <boost/python/self.hpp>
+#include <boost/python/dict.hpp>
+#include <boost/python/str.hpp>
+#include <boost/python/ssize_t.hpp>
+#include <functional>
+#include <vector>
+#include <cstddef>
+#include <new>
+#include <structmember.h>
+
+namespace boost { namespace python {
+
+# ifdef BOOST_PYTHON_SELF_IS_CLASS
+namespace self_ns
+{
+ self_t self;
+}
+# endif
+
+instance_holder::instance_holder()
+ : m_next(0)
+{
+}
+
+instance_holder::~instance_holder()
+{
+}
+
+extern "C"
+{
+ // This is copied from typeobject.c in the Python sources. Even though
+ // class_metatype_object doesn't set Py_TPFLAGS_HAVE_GC, that bit gets
+ // filled in by the base class initialization process in
+ // PyType_Ready(). However, tp_is_gc is *not* copied from the base
+ // type, making it assume that classes are GC-able even if (like
+ // class_type_object) they're statically allocated.
+ static int
+ type_is_gc(PyTypeObject *python_type)
+ {
+ return python_type->tp_flags & Py_TPFLAGS_HEAPTYPE;
+ }
+
+ // This is also copied from the Python sources. We can't implement
+ // static_data as a subclass property effectively without it.
+ typedef struct {
+ PyObject_HEAD
+ PyObject *prop_get;
+ PyObject *prop_set;
+ PyObject *prop_del;
+ PyObject *prop_doc;
+ int getter_doc;
+ } propertyobject;
+
+ // Copied from Python source and removed the part for setting docstring,
+ // since we don't have a setter for __doc__ and trying to set it will
+ // cause the init fail.
+ static int property_init(PyObject *self, PyObject *args, PyObject *kwds)
+ {
+ PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
+ static const char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
+ propertyobject *prop = (propertyobject *)self;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
+ const_cast<char **>(kwlist), &get, &set, &del, &doc))
+ return -1;
+
+ if (get == Py_None)
+ get = NULL;
+ if (set == Py_None)
+ set = NULL;
+ if (del == Py_None)
+ del = NULL;
+
+ Py_XINCREF(get);
+ Py_XINCREF(set);
+ Py_XINCREF(del);
+ Py_XINCREF(doc);
+
+ prop->prop_get = get;
+ prop->prop_set = set;
+ prop->prop_del = del;
+ prop->prop_doc = doc;
+ prop->getter_doc = 0;
+
+ return 0;
+ }
+
+
+ static PyObject *
+ static_data_descr_get(PyObject *self, PyObject * /*obj*/, PyObject * /*type*/)
+ {
+ propertyobject *gs = (propertyobject *)self;
+
+ return PyObject_CallFunction(gs->prop_get, const_cast<char*>("()"));
+ }
+
+ static int
+ static_data_descr_set(PyObject *self, PyObject * /*obj*/, PyObject *value)
+ {
+ propertyobject *gs = (propertyobject *)self;
+ PyObject *func, *res;
+
+ if (value == NULL)
+ func = gs->prop_del;
+ else
+ func = gs->prop_set;
+ if (func == NULL) {
+ PyErr_SetString(PyExc_AttributeError,
+ value == NULL ?
+ "can't delete attribute" :
+ "can't set attribute");
+ return -1;
+ }
+ if (value == NULL)
+ res = PyObject_CallFunction(func, const_cast<char*>("()"));
+ else
+ res = PyObject_CallFunction(func, const_cast<char*>("(O)"), value);
+ if (res == NULL)
+ return -1;
+ Py_DECREF(res);
+ return 0;
+ }
+}
+
+static PyTypeObject static_data_object = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ const_cast<char*>("Boost.Python.StaticProperty"),
+ sizeof(propertyobject),
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
+ | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, //&PyProperty_Type, /* tp_base */
+ 0, /* tp_dict */
+ static_data_descr_get, /* tp_descr_get */
+ static_data_descr_set, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ property_init, /* tp_init */
+ 0, /* tp_alloc */
+ 0, // filled in with type_new /* tp_new */
+ 0, // filled in with __PyObject_GC_Del /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+#if PYTHON_API_VERSION >= 1012
+ 0 /* tp_del */
+#endif
+};
+
+namespace objects
+{
+#if PY_VERSION_HEX < 0x03000000
+ // XXX Not sure why this run into compiling error in Python 3
+ extern "C"
+ {
+ // This declaration needed due to broken Python 2.2 headers
+ extern DL_IMPORT(PyTypeObject) PyProperty_Type;
+ }
+#endif
+
+ BOOST_PYTHON_DECL PyObject* static_data()
+ {
+ if (static_data_object.tp_dict == 0)
+ {
+ Py_TYPE(&static_data_object) = &PyType_Type;
+ static_data_object.tp_base = &PyProperty_Type;
+ if (PyType_Ready(&static_data_object))
+ return 0;
+ }
+ return upcast<PyObject>(&static_data_object);
+ }
+}
+
+extern "C"
+{
+ // Ordinarily, descriptors have a certain assymetry: you can use
+ // them to read attributes off the class object they adorn, but
+ // writing the same attribute on the class object always replaces
+ // the descriptor in the class __dict__. In order to properly
+ // represent C++ static data members, we need to allow them to be
+ // written through the class instance. This function of the
+ // metaclass makes it possible.
+ static int
+ class_setattro(PyObject *obj, PyObject *name, PyObject* value)
+ {
+ // Must use "private" Python implementation detail
+ // _PyType_Lookup instead of PyObject_GetAttr because the
+ // latter will always end up calling the descr_get function on
+ // any descriptor it finds; we need the unadulterated
+ // descriptor here.
+ PyObject* a = _PyType_Lookup(downcast<PyTypeObject>(obj), name);
+
+ // a is a borrowed reference or 0
+
+ // If we found a static data descriptor, call it directly to
+ // force it to set the static data member
+ if (a != 0 && PyObject_IsInstance(a, objects::static_data()))
+ return Py_TYPE(a)->tp_descr_set(a, obj, value);
+ else
+ return PyType_Type.tp_setattro(obj, name, value);
+ }
+}
+
+static PyTypeObject class_metatype_object = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ const_cast<char*>("Boost.Python.class"),
+ PyType_Type.tp_basicsize,
+ 0,
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ class_setattro, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
+ | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, //&PyType_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, // filled in with type_new /* tp_new */
+ 0, // filled in with __PyObject_GC_Del /* tp_free */
+ (inquiry)type_is_gc, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+#if PYTHON_API_VERSION >= 1012
+ 0 /* tp_del */
+#endif
+};
+
+// Install the instance data for a C++ object into a Python instance
+// object.
void instance_holder::install(PyObject* self) noexcept
-{
- assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self)), &class_metatype_object));
- m_next = ((objects::instance<>*)self)->objects;
- ((objects::instance<>*)self)->objects = this;
-}
-
-
-namespace objects
-{
-// Get the metatype object for all extension classes.
- BOOST_PYTHON_DECL type_handle class_metatype()
- {
- if (class_metatype_object.tp_dict == 0)
- {
- Py_TYPE(&class_metatype_object) = &PyType_Type;
- class_metatype_object.tp_base = &PyType_Type;
- if (PyType_Ready(&class_metatype_object))
- return type_handle();
- }
- return type_handle(borrowed(&class_metatype_object));
- }
- extern "C"
- {
- static void instance_dealloc(PyObject* inst)
- {
- instance<>* kill_me = (instance<>*)inst;
-
- for (instance_holder* p = kill_me->objects, *next; p != 0; p = next)
- {
- next = p->next();
- p->~instance_holder();
- instance_holder::deallocate(inst, dynamic_cast<void*>(p));
- }
-
- // Python 2.2.1 won't add weak references automatically when
- // tp_itemsize > 0, so we need to manage that
- // ourselves. Accordingly, we also have to clean up the
- // weakrefs ourselves.
- if (kill_me->weakrefs != NULL)
- PyObject_ClearWeakRefs(inst);
-
- Py_XDECREF(kill_me->dict);
-
- Py_TYPE(inst)->tp_free(inst);
- }
-
- static PyObject *
- instance_new(PyTypeObject* type_, PyObject* /*args*/, PyObject* /*kw*/)
- {
- // Attempt to find the __instance_size__ attribute. If not present, no problem.
- PyObject* d = type_->tp_dict;
- PyObject* instance_size_obj = PyObject_GetAttrString(d, const_cast<char*>("__instance_size__"));
-
- ssize_t instance_size = instance_size_obj ?
-#if PY_VERSION_HEX >= 0x03000000
- PyLong_AsSsize_t(instance_size_obj) : 0;
-#else
- PyInt_AsLong(instance_size_obj) : 0;
-#endif
-
- if (instance_size < 0)
- instance_size = 0;
-
- PyErr_Clear(); // Clear any errors that may have occurred.
-
- instance<>* result = (instance<>*)type_->tp_alloc(type_, instance_size);
- if (result)
- {
- // Guido says we can use ob_size for any purpose we
- // like, so we'll store the total size of the object
- // there. A negative number indicates that the extra
- // instance memory is not yet allocated to any holders.
-#if PY_VERSION_HEX >= 0x02060000
- Py_SIZE(result) =
-#else
- result->ob_size =
-#endif
- -(static_cast<int>(offsetof(instance<>,storage) + instance_size));
- }
- return (PyObject*)result;
- }
-
- static PyObject* instance_get_dict(PyObject* op, void*)
- {
- instance<>* inst = downcast<instance<> >(op);
- if (inst->dict == 0)
- inst->dict = PyDict_New();
- return python::xincref(inst->dict);
- }
-
- static int instance_set_dict(PyObject* op, PyObject* dict, void*)
- {
- instance<>* inst = downcast<instance<> >(op);
- python::xdecref(inst->dict);
- inst->dict = python::incref(dict);
- return 0;
- }
-
- }
-
-
- static PyGetSetDef instance_getsets[] = {
- {const_cast<char*>("__dict__"), instance_get_dict, instance_set_dict, NULL, 0},
- {0, 0, 0, 0, 0}
- };
-
-
- static PyMemberDef instance_members[] = {
- {const_cast<char*>("__weakref__"), T_OBJECT, offsetof(instance<>, weakrefs), 0, 0},
- {0, 0, 0, 0, 0}
- };
-
- static PyTypeObject class_type_object = {
- PyVarObject_HEAD_INIT(NULL, 0)
- const_cast<char*>("Boost.Python.instance"),
- offsetof(instance<>,storage), /* tp_basicsize */
- 1, /* tp_itemsize */
- instance_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
- | Py_TPFLAGS_BASETYPE, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(instance<>,weakrefs), /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- instance_members, /* tp_members */
- instance_getsets, /* tp_getset */
- 0, //&PyBaseObject_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(instance<>,dict), /* tp_dictoffset */
- 0, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- instance_new, /* tp_new */
- 0, /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
-#if PYTHON_API_VERSION >= 1012
- 0 /* tp_del */
-#endif
- };
-
- BOOST_PYTHON_DECL type_handle class_type()
- {
- if (class_type_object.tp_dict == 0)
- {
- Py_TYPE(&class_type_object) = incref(class_metatype().get());
- class_type_object.tp_base = &PyBaseObject_Type;
- if (PyType_Ready(&class_type_object))
- return type_handle();
-// class_type_object.tp_setattro = class_setattro;
- }
- return type_handle(borrowed(&class_type_object));
- }
-
- BOOST_PYTHON_DECL void*
- find_instance_impl(PyObject* inst, type_info type, bool null_shared_ptr_only)
- {
- if (!Py_TYPE(Py_TYPE(inst)) ||
- !PyType_IsSubtype(Py_TYPE(Py_TYPE(inst)), &class_metatype_object))
- return 0;
-
- instance<>* self = reinterpret_cast<instance<>*>(inst);
-
- for (instance_holder* match = self->objects; match != 0; match = match->next())
- {
- void* const found = match->holds(type, null_shared_ptr_only);
- if (found)
- return found;
- }
- return 0;
- }
-
- object module_prefix()
- {
- return object(
- PyObject_IsInstance(scope().ptr(), upcast<PyObject>(&PyModule_Type))
- ? object(scope().attr("__name__"))
- : api::getattr(scope(), "__module__", str())
- );
- }
-
- namespace
- {
- // Find a registered class object corresponding to id. Return a
- // null handle if no such class is registered.
- inline type_handle query_class(type_info id)
- {
- converter::registration const* p = converter::registry::query(id);
- return type_handle(
- python::borrowed(
- python::allow_null(p ? p->m_class_object : 0))
- );
- }
-
- // Find a registered class corresponding to id. If not found,
- // throw an appropriate exception.
- type_handle get_class(type_info id)
- {
- type_handle result(query_class(id));
-
- if (result.get() == 0)
- {
- object report("extension class wrapper for base class ");
- report = report + id.name() + " has not been created yet";
- PyErr_SetObject(PyExc_RuntimeError, report.ptr());
- throw_error_already_set();
- }
- return result;
- }
-
- // class_base constructor
- //
- // name - the name of the new Python class
- //
- // num_types - one more than the number of declared bases
- //
- // types - array of python::type_info, the first item
- // corresponding to the class being created, and the
- // rest corresponding to its declared bases.
- //
- inline object
- new_class(char const* name, std::size_t num_types, type_info const* const types, char const* doc)
- {
- assert(num_types >= 1);
-
- // Build a tuple of the base Python type objects. If no bases
- // were declared, we'll use our class_type() as the single base
- // class.
- ssize_t const num_bases = (std::max)(num_types - 1, static_cast<std::size_t>(1));
- handle<> bases(PyTuple_New(num_bases));
-
- for (ssize_t i = 1; i <= num_bases; ++i)
- {
- type_handle c = (i >= static_cast<ssize_t>(num_types)) ? class_type() : get_class(types[i]);
- // PyTuple_SET_ITEM steals this reference
- PyTuple_SET_ITEM(bases.get(), static_cast<ssize_t>(i - 1), upcast<PyObject>(c.release()));
- }
-
- // Call the class metatype to create a new class
- dict d;
+{
+ assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self)), &class_metatype_object));
+ m_next = ((objects::instance<>*)self)->objects;
+ ((objects::instance<>*)self)->objects = this;
+}
+
+
+namespace objects
+{
+// Get the metatype object for all extension classes.
+ BOOST_PYTHON_DECL type_handle class_metatype()
+ {
+ if (class_metatype_object.tp_dict == 0)
+ {
+ Py_TYPE(&class_metatype_object) = &PyType_Type;
+ class_metatype_object.tp_base = &PyType_Type;
+ if (PyType_Ready(&class_metatype_object))
+ return type_handle();
+ }
+ return type_handle(borrowed(&class_metatype_object));
+ }
+ extern "C"
+ {
+ static void instance_dealloc(PyObject* inst)
+ {
+ instance<>* kill_me = (instance<>*)inst;
+
+ for (instance_holder* p = kill_me->objects, *next; p != 0; p = next)
+ {
+ next = p->next();
+ p->~instance_holder();
+ instance_holder::deallocate(inst, dynamic_cast<void*>(p));
+ }
+
+ // Python 2.2.1 won't add weak references automatically when
+ // tp_itemsize > 0, so we need to manage that
+ // ourselves. Accordingly, we also have to clean up the
+ // weakrefs ourselves.
+ if (kill_me->weakrefs != NULL)
+ PyObject_ClearWeakRefs(inst);
+
+ Py_XDECREF(kill_me->dict);
+
+ Py_TYPE(inst)->tp_free(inst);
+ }
+
+ static PyObject *
+ instance_new(PyTypeObject* type_, PyObject* /*args*/, PyObject* /*kw*/)
+ {
+ // Attempt to find the __instance_size__ attribute. If not present, no problem.
+ PyObject* d = type_->tp_dict;
+ PyObject* instance_size_obj = PyObject_GetAttrString(d, const_cast<char*>("__instance_size__"));
+
+ ssize_t instance_size = instance_size_obj ?
+#if PY_VERSION_HEX >= 0x03000000
+ PyLong_AsSsize_t(instance_size_obj) : 0;
+#else
+ PyInt_AsLong(instance_size_obj) : 0;
+#endif
+
+ if (instance_size < 0)
+ instance_size = 0;
+
+ PyErr_Clear(); // Clear any errors that may have occurred.
+
+ instance<>* result = (instance<>*)type_->tp_alloc(type_, instance_size);
+ if (result)
+ {
+ // Guido says we can use ob_size for any purpose we
+ // like, so we'll store the total size of the object
+ // there. A negative number indicates that the extra
+ // instance memory is not yet allocated to any holders.
+#if PY_VERSION_HEX >= 0x02060000
+ Py_SIZE(result) =
+#else
+ result->ob_size =
+#endif
+ -(static_cast<int>(offsetof(instance<>,storage) + instance_size));
+ }
+ return (PyObject*)result;
+ }
+
+ static PyObject* instance_get_dict(PyObject* op, void*)
+ {
+ instance<>* inst = downcast<instance<> >(op);
+ if (inst->dict == 0)
+ inst->dict = PyDict_New();
+ return python::xincref(inst->dict);
+ }
- object m = module_prefix();
- if (m) d["__module__"] = m;
-
- if (doc != 0)
- d["__doc__"] = doc;
-
- object result = object(class_metatype())(name, bases, d);
- assert(PyType_IsSubtype(Py_TYPE(result.ptr()), &PyType_Type));
-
- if (scope().ptr() != Py_None)
- scope().attr(name) = result;
-
- // For pickle. Will lead to informative error messages if pickling
- // is not enabled.
- result.attr("__reduce__") = object(make_instance_reduce_function());
-
- return result;
- }
- }
-
- class_base::class_base(
- char const* name, std::size_t num_types, type_info const* const types, char const* doc)
- : object(new_class(name, num_types, types, doc))
- {
- // Insert the new class object in the registry
- converter::registration& converters = const_cast<converter::registration&>(
- converter::registry::lookup(types[0]));
-
- // Class object is leaked, for now
- converters.m_class_object = (PyTypeObject*)incref(this->ptr());
- }
-
- BOOST_PYTHON_DECL void copy_class_object(type_info const& src, type_info const& dst)
- {
- converter::registration& dst_converters
- = const_cast<converter::registration&>(converter::registry::lookup(dst));
-
- converter::registration const& src_converters = converter::registry::lookup(src);
-
- dst_converters.m_class_object = src_converters.m_class_object;
- }
-
- void class_base::set_instance_size(std::size_t instance_size)
- {
- this->attr("__instance_size__") = instance_size;
- }
+ static int instance_set_dict(PyObject* op, PyObject* dict, void*)
+ {
+ instance<>* inst = downcast<instance<> >(op);
+ python::xdecref(inst->dict);
+ inst->dict = python::incref(dict);
+ return 0;
+ }
+
+ }
+
+
+ static PyGetSetDef instance_getsets[] = {
+ {const_cast<char*>("__dict__"), instance_get_dict, instance_set_dict, NULL, 0},
+ {0, 0, 0, 0, 0}
+ };
+
+
+ static PyMemberDef instance_members[] = {
+ {const_cast<char*>("__weakref__"), T_OBJECT, offsetof(instance<>, weakrefs), 0, 0},
+ {0, 0, 0, 0, 0}
+ };
+
+ static PyTypeObject class_type_object = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ const_cast<char*>("Boost.Python.instance"),
+ offsetof(instance<>,storage), /* tp_basicsize */
+ 1, /* tp_itemsize */
+ instance_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT // | Py_TPFLAGS_HAVE_GC
+ | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ offsetof(instance<>,weakrefs), /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ instance_members, /* tp_members */
+ instance_getsets, /* tp_getset */
+ 0, //&PyBaseObject_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ offsetof(instance<>,dict), /* tp_dictoffset */
+ 0, /* tp_init */
+ PyType_GenericAlloc, /* tp_alloc */
+ instance_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+#if PYTHON_API_VERSION >= 1012
+ 0 /* tp_del */
+#endif
+ };
+
+ BOOST_PYTHON_DECL type_handle class_type()
+ {
+ if (class_type_object.tp_dict == 0)
+ {
+ Py_TYPE(&class_type_object) = incref(class_metatype().get());
+ class_type_object.tp_base = &PyBaseObject_Type;
+ if (PyType_Ready(&class_type_object))
+ return type_handle();
+// class_type_object.tp_setattro = class_setattro;
+ }
+ return type_handle(borrowed(&class_type_object));
+ }
+
+ BOOST_PYTHON_DECL void*
+ find_instance_impl(PyObject* inst, type_info type, bool null_shared_ptr_only)
+ {
+ if (!Py_TYPE(Py_TYPE(inst)) ||
+ !PyType_IsSubtype(Py_TYPE(Py_TYPE(inst)), &class_metatype_object))
+ return 0;
+
+ instance<>* self = reinterpret_cast<instance<>*>(inst);
+
+ for (instance_holder* match = self->objects; match != 0; match = match->next())
+ {
+ void* const found = match->holds(type, null_shared_ptr_only);
+ if (found)
+ return found;
+ }
+ return 0;
+ }
+
+ object module_prefix()
+ {
+ return object(
+ PyObject_IsInstance(scope().ptr(), upcast<PyObject>(&PyModule_Type))
+ ? object(scope().attr("__name__"))
+ : api::getattr(scope(), "__module__", str())
+ );
+ }
+
+ namespace
+ {
+ // Find a registered class object corresponding to id. Return a
+ // null handle if no such class is registered.
+ inline type_handle query_class(type_info id)
+ {
+ converter::registration const* p = converter::registry::query(id);
+ return type_handle(
+ python::borrowed(
+ python::allow_null(p ? p->m_class_object : 0))
+ );
+ }
+
+ // Find a registered class corresponding to id. If not found,
+ // throw an appropriate exception.
+ type_handle get_class(type_info id)
+ {
+ type_handle result(query_class(id));
+
+ if (result.get() == 0)
+ {
+ object report("extension class wrapper for base class ");
+ report = report + id.name() + " has not been created yet";
+ PyErr_SetObject(PyExc_RuntimeError, report.ptr());
+ throw_error_already_set();
+ }
+ return result;
+ }
+
+ // class_base constructor
+ //
+ // name - the name of the new Python class
+ //
+ // num_types - one more than the number of declared bases
+ //
+ // types - array of python::type_info, the first item
+ // corresponding to the class being created, and the
+ // rest corresponding to its declared bases.
+ //
+ inline object
+ new_class(char const* name, std::size_t num_types, type_info const* const types, char const* doc)
+ {
+ assert(num_types >= 1);
+
+ // Build a tuple of the base Python type objects. If no bases
+ // were declared, we'll use our class_type() as the single base
+ // class.
+ ssize_t const num_bases = (std::max)(num_types - 1, static_cast<std::size_t>(1));
+ handle<> bases(PyTuple_New(num_bases));
+
+ for (ssize_t i = 1; i <= num_bases; ++i)
+ {
+ type_handle c = (i >= static_cast<ssize_t>(num_types)) ? class_type() : get_class(types[i]);
+ // PyTuple_SET_ITEM steals this reference
+ PyTuple_SET_ITEM(bases.get(), static_cast<ssize_t>(i - 1), upcast<PyObject>(c.release()));
+ }
+
+ // Call the class metatype to create a new class
+ dict d;
- void class_base::add_property(
- char const* name, object const& fget, char const* docstr)
- {
- object property(
- (python::detail::new_reference)
- PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("Osss"), fget.ptr(), 0, 0, docstr));
-
- this->setattr(name, property);
- }
-
- void class_base::add_property(
- char const* name, object const& fget, object const& fset, char const* docstr)
- {
- object property(
- (python::detail::new_reference)
- PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("OOss"), fget.ptr(), fset.ptr(), 0, docstr));
-
- this->setattr(name, property);
- }
-
- void class_base::add_static_property(char const* name, object const& fget)
- {
- object property(
- (python::detail::new_reference)
- PyObject_CallFunction(static_data(), const_cast<char*>("O"), fget.ptr())
- );
-
- this->setattr(name, property);
- }
-
- void class_base::add_static_property(char const* name, object const& fget, object const& fset)
- {
- object property(
+ object m = module_prefix();
+ if (m) d["__module__"] = m;
+
+ if (doc != 0)
+ d["__doc__"] = doc;
+
+ object result = object(class_metatype())(name, bases, d);
+ assert(PyType_IsSubtype(Py_TYPE(result.ptr()), &PyType_Type));
+
+ if (scope().ptr() != Py_None)
+ scope().attr(name) = result;
+
+ // For pickle. Will lead to informative error messages if pickling
+ // is not enabled.
+ result.attr("__reduce__") = object(make_instance_reduce_function());
+
+ return result;
+ }
+ }
+
+ class_base::class_base(
+ char const* name, std::size_t num_types, type_info const* const types, char const* doc)
+ : object(new_class(name, num_types, types, doc))
+ {
+ // Insert the new class object in the registry
+ converter::registration& converters = const_cast<converter::registration&>(
+ converter::registry::lookup(types[0]));
+
+ // Class object is leaked, for now
+ converters.m_class_object = (PyTypeObject*)incref(this->ptr());
+ }
+
+ BOOST_PYTHON_DECL void copy_class_object(type_info const& src, type_info const& dst)
+ {
+ converter::registration& dst_converters
+ = const_cast<converter::registration&>(converter::registry::lookup(dst));
+
+ converter::registration const& src_converters = converter::registry::lookup(src);
+
+ dst_converters.m_class_object = src_converters.m_class_object;
+ }
+
+ void class_base::set_instance_size(std::size_t instance_size)
+ {
+ this->attr("__instance_size__") = instance_size;
+ }
+
+ void class_base::add_property(
+ char const* name, object const& fget, char const* docstr)
+ {
+ object property(
+ (python::detail::new_reference)
+ PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("Osss"), fget.ptr(), 0, 0, docstr));
+
+ this->setattr(name, property);
+ }
+
+ void class_base::add_property(
+ char const* name, object const& fget, object const& fset, char const* docstr)
+ {
+ object property(
+ (python::detail::new_reference)
+ PyObject_CallFunction((PyObject*)&PyProperty_Type, const_cast<char*>("OOss"), fget.ptr(), fset.ptr(), 0, docstr));
+
+ this->setattr(name, property);
+ }
+
+ void class_base::add_static_property(char const* name, object const& fget)
+ {
+ object property(
(python::detail::new_reference)
- PyObject_CallFunction(static_data(), const_cast<char*>("OO"), fget.ptr(), fset.ptr()));
-
- this->setattr(name, property);
- }
-
- void class_base::setattr(char const* name, object const& x)
- {
- if (PyObject_SetAttrString(this->ptr(), const_cast<char*>(name), x.ptr()) < 0)
- throw_error_already_set();
- }
-
- namespace
- {
- extern "C" PyObject* no_init(PyObject*, PyObject*)
- {
- ::PyErr_SetString(::PyExc_RuntimeError, const_cast<char*>("This class cannot be instantiated from Python"));
- return NULL;
- }
- static ::PyMethodDef no_init_def = {
- const_cast<char*>("__init__"), no_init, METH_VARARGS,
- const_cast<char*>("Raises an exception\n"
- "This class cannot be instantiated from Python\n")
- };
- }
-
- void class_base::def_no_init()
- {
- handle<> f(::PyCFunction_New(&no_init_def, 0));
- this->setattr("__init__", object(f));
- }
-
- void class_base::enable_pickling_(bool getstate_manages_dict)
- {
- setattr("__safe_for_unpickling__", object(true));
-
- if (getstate_manages_dict)
- {
- setattr("__getstate_manages_dict__", object(true));
- }
- }
-
- namespace
- {
- PyObject* callable_check(PyObject* callable)
- {
- if (PyCallable_Check(expect_non_null(callable)))
- return callable;
-
- ::PyErr_Format(
- PyExc_TypeError
- , const_cast<char*>("staticmethod expects callable object; got an object of type %s, which is not callable")
- , Py_TYPE(callable)->tp_name
- );
-
- throw_error_already_set();
- return 0;
- }
- }
-
- void class_base::make_method_static(const char * method_name)
- {
- PyTypeObject* self = downcast<PyTypeObject>(this->ptr());
- dict d((handle<>(borrowed(self->tp_dict))));
-
- object method(d[method_name]);
-
- this->attr(method_name) = object(
- handle<>(
- PyStaticMethod_New((callable_check)(method.ptr()) )
- ));
- }
-
- BOOST_PYTHON_DECL type_handle registered_class_object(type_info id)
- {
- return query_class(id);
- }
-} // namespace objects
-
-
-void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size)
-{
- assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object));
- objects::instance<>* self = (objects::instance<>*)self_;
-
- int total_size_needed = holder_offset + holder_size;
-
- if (-Py_SIZE(self) >= total_size_needed)
- {
- // holder_offset should at least point into the variable-sized part
- assert(holder_offset >= offsetof(objects::instance<>,storage));
-
- // Record the fact that the storage is occupied, noting where it starts
- Py_SIZE(self) = holder_offset;
- return (char*)self + holder_offset;
- }
- else
- {
- void* const result = PyMem_Malloc(holder_size);
- if (result == 0)
- throw std::bad_alloc();
- return result;
- }
-}
-
+ PyObject_CallFunction(static_data(), const_cast<char*>("O"), fget.ptr())
+ );
+
+ this->setattr(name, property);
+ }
+
+ void class_base::add_static_property(char const* name, object const& fget, object const& fset)
+ {
+ object property(
+ (python::detail::new_reference)
+ PyObject_CallFunction(static_data(), const_cast<char*>("OO"), fget.ptr(), fset.ptr()));
+
+ this->setattr(name, property);
+ }
+
+ void class_base::setattr(char const* name, object const& x)
+ {
+ if (PyObject_SetAttrString(this->ptr(), const_cast<char*>(name), x.ptr()) < 0)
+ throw_error_already_set();
+ }
+
+ namespace
+ {
+ extern "C" PyObject* no_init(PyObject*, PyObject*)
+ {
+ ::PyErr_SetString(::PyExc_RuntimeError, const_cast<char*>("This class cannot be instantiated from Python"));
+ return NULL;
+ }
+ static ::PyMethodDef no_init_def = {
+ const_cast<char*>("__init__"), no_init, METH_VARARGS,
+ const_cast<char*>("Raises an exception\n"
+ "This class cannot be instantiated from Python\n")
+ };
+ }
+
+ void class_base::def_no_init()
+ {
+ handle<> f(::PyCFunction_New(&no_init_def, 0));
+ this->setattr("__init__", object(f));
+ }
+
+ void class_base::enable_pickling_(bool getstate_manages_dict)
+ {
+ setattr("__safe_for_unpickling__", object(true));
+
+ if (getstate_manages_dict)
+ {
+ setattr("__getstate_manages_dict__", object(true));
+ }
+ }
+
+ namespace
+ {
+ PyObject* callable_check(PyObject* callable)
+ {
+ if (PyCallable_Check(expect_non_null(callable)))
+ return callable;
+
+ ::PyErr_Format(
+ PyExc_TypeError
+ , const_cast<char*>("staticmethod expects callable object; got an object of type %s, which is not callable")
+ , Py_TYPE(callable)->tp_name
+ );
+
+ throw_error_already_set();
+ return 0;
+ }
+ }
+
+ void class_base::make_method_static(const char * method_name)
+ {
+ PyTypeObject* self = downcast<PyTypeObject>(this->ptr());
+ dict d((handle<>(borrowed(self->tp_dict))));
+
+ object method(d[method_name]);
+
+ this->attr(method_name) = object(
+ handle<>(
+ PyStaticMethod_New((callable_check)(method.ptr()) )
+ ));
+ }
+
+ BOOST_PYTHON_DECL type_handle registered_class_object(type_info id)
+ {
+ return query_class(id);
+ }
+} // namespace objects
+
+
+void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size)
+{
+ assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object));
+ objects::instance<>* self = (objects::instance<>*)self_;
+
+ int total_size_needed = holder_offset + holder_size;
+
+ if (-Py_SIZE(self) >= total_size_needed)
+ {
+ // holder_offset should at least point into the variable-sized part
+ assert(holder_offset >= offsetof(objects::instance<>,storage));
+
+ // Record the fact that the storage is occupied, noting where it starts
+ Py_SIZE(self) = holder_offset;
+ return (char*)self + holder_offset;
+ }
+ else
+ {
+ void* const result = PyMem_Malloc(holder_size);
+ if (result == 0)
+ throw std::bad_alloc();
+ return result;
+ }
+}
+
void instance_holder::deallocate(PyObject* self_, void* storage) noexcept
-{
- assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object));
- objects::instance<>* self = (objects::instance<>*)self_;
- if (storage != (char*)self + Py_SIZE(self))
- {
- PyMem_Free(storage);
- }
-}
-
-}} // namespace boost::python
+{
+ assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object));
+ objects::instance<>* self = (objects::instance<>*)self_;
+ if (storage != (char*)self + Py_SIZE(self))
+ {
+ PyMem_Free(storage);
+ }
+}
+
+}} // namespace boost::python