class.cpp

来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 718 行 · 第 1/2 页

CPP
718
字号
// 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_CLASSnamespace 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;  } propertyobject;  static PyObject *  static_data_descr_get(PyObject *self, PyObject * /*obj*/, PyObject * /*type*/)  {      propertyobject *gs = (propertyobject *)self;      return PyObject_CallFunction(gs->prop_get, "()");  }  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, "()");      else          res = PyObject_CallFunction(func, "(O)", value);      if (res == NULL)          return -1;      Py_DECREF(res);      return 0;  }}static PyTypeObject static_data_object = {    PyObject_HEAD_INIT(0)//&PyType_Type)    0,    "Boost.Python.StaticProperty",    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 */    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 */    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};namespace objects{  extern "C"  {      // This declaration needed due to broken Python 2.2 headers      extern DL_IMPORT(PyTypeObject) PyProperty_Type;  }  BOOST_PYTHON_DECL PyObject* static_data()  {      if (static_data_object.tp_dict == 0)      {          static_data_object.ob_type = &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 a->ob_type->tp_descr_set(a, obj, value);        else            return PyType_Type.tp_setattro(obj, name, value);    }}static PyTypeObject class_metatype_object = {    PyObject_HEAD_INIT(0)//&PyType_Type)    0,    "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) throw(){    assert(self->ob_type->ob_type == &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)      {          class_metatype_object.ob_type = &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);                    inst->ob_type->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, "__instance_size__");          long instance_size = instance_size_obj ? PyInt_AsLong(instance_size_obj) : 0;                    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.              result->ob_size = -(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[] = {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?