class.cpp

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

CPP
718
字号
      {"__dict__",  instance_get_dict,  instance_set_dict, NULL, 0},      {0, 0, 0, 0, 0}  };    static PyMemberDef instance_members[] = {      {"__weakref__", T_OBJECT, offsetof(instance<>, weakrefs), 0, 0},      {0, 0, 0, 0, 0}  };  static PyTypeObject class_type_object = {      PyObject_HEAD_INIT(0) //&class_metatype_object)      0,      "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)      {          class_type_object.ob_type = 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 (inst->ob_type->ob_type != &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.      std::size_t const num_bases = (std::max)(num_types - 1, static_cast<std::size_t>(1));      assert(num_bases <= ssize_t_max);      handle<> bases(PyTuple_New(static_cast<ssize_t>(num_bases)));      for (std::size_t i = 1; i <= num_bases; ++i)      {          type_handle c = (i >= 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;         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(result.ptr()->ob_type, &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, "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, "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(), "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(), "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, "This class cannot be instantiated from Python");        return NULL;    }    static ::PyMethodDef no_init_def = {        "__init__", no_init, METH_VARARGS,        "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            , "staticmethod expects callable object; got an object of type %s, which is not callable"            , callable->ob_type->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 objectsvoid* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size){    assert(self_->ob_type->ob_type == &class_metatype_object);    objects::instance<>* self = (objects::instance<>*)self_;        int total_size_needed = holder_offset + holder_size;        if (-self->ob_size >= 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        self->ob_size = 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) throw(){    assert(self_->ob_type->ob_type == &class_metatype_object);    objects::instance<>* self = (objects::instance<>*)self_;    if (storage != (char*)self + self->ob_size)    {        PyMem_Free(storage);    }}}} // namespace boost::python

⌨️ 快捷键说明

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