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 + -
显示快捷键?