function.cpp
来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 762 行 · 第 1/2 页
CPP
762 行
}; inline bool is_binary_operator(char const* name) { return name[0] == '_' && name[1] == '_' && std::binary_search( &binary_operator_names[0] , binary_operator_names + sizeof(binary_operator_names)/sizeof(*binary_operator_names) , name + 2 , less_cstring() ); } // Something for the end of the chain of binary operators PyObject* not_implemented(PyObject*, PyObject*) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } handle<function> not_implemented_function() { static object keeper( function_object( py_function(¬_implemented, mpl::vector1<void>(), 2) , python::detail::keyword_range()) ); return handle<function>(borrowed(downcast<function>(keeper.ptr()))); }}void function::add_to_namespace( object const& name_space, char const* name_, object const& attribute){ add_to_namespace(name_space, name_, attribute, 0);}namespace detail{ extern char py_signature_tag[]; extern char cpp_signature_tag[];}void function::add_to_namespace( object const& name_space, char const* name_, object const& attribute, char const* doc){ str const name(name_); PyObject* const ns = name_space.ptr(); if (attribute.ptr()->ob_type == &function_type) { function* new_func = downcast<function>(attribute.ptr()); PyObject* dict = 0; if (PyClass_Check(ns)) dict = ((PyClassObject*)ns)->cl_dict; else if (PyType_Check(ns)) dict = ((PyTypeObject*)ns)->tp_dict; else dict = PyObject_GetAttrString(ns, "__dict__"); if (dict == 0) throw_error_already_set(); handle<> existing(allow_null(::PyObject_GetItem(dict, name.ptr()))); if (existing) { if (existing->ob_type == &function_type) { new_func->add_overload( handle<function>( borrowed( downcast<function>(existing.get()) ) ) ); } else if (existing->ob_type == &PyStaticMethod_Type) { char const* name_space_name = extract<char const*>(name_space.attr("__name__")); ::PyErr_Format( PyExc_RuntimeError , "Boost.Python - All overloads must be exported " "before calling \'class_<...>(\"%s\").staticmethod(\"%s\")\'" , name_space_name , name_ ); throw_error_already_set(); } } else if (is_binary_operator(name_)) { // Binary operators need an additional overload which // returns NotImplemented, so that Python will try the // __rxxx__ functions on the other operand. We add this // when no overloads for the operator already exist. new_func->add_overload(not_implemented_function()); } // A function is named the first time it is added to a namespace. if (new_func->name().ptr() == Py_None) new_func->m_name = name; handle<> name_space_name( allow_null(::PyObject_GetAttrString(name_space.ptr(), "__name__"))); if (name_space_name) new_func->m_namespace = object(name_space_name); } // The PyObject_GetAttrString() or PyObject_GetItem calls above may // have left an active error PyErr_Clear(); if (PyObject_SetAttr(ns, name.ptr(), attribute.ptr()) < 0) throw_error_already_set(); object mutable_attribute(attribute);/* if (doc != 0 && docstring_options::show_user_defined_) { // Accumulate documentation if ( PyObject_HasAttrString(mutable_attribute.ptr(), "__doc__") && mutable_attribute.attr("__doc__")) { mutable_attribute.attr("__doc__") += "\n\n"; mutable_attribute.attr("__doc__") += doc; } else { mutable_attribute.attr("__doc__") = doc; } } if (docstring_options::show_signatures_) { if ( PyObject_HasAttrString(mutable_attribute.ptr(), "__doc__") && mutable_attribute.attr("__doc__")) { mutable_attribute.attr("__doc__") += ( mutable_attribute.attr("__doc__")[-1] != "\n" ? "\n\n" : "\n"); } else { mutable_attribute.attr("__doc__") = ""; } function* f = downcast<function>(attribute.ptr()); mutable_attribute.attr("__doc__") += str("\n ").join(make_tuple( "C++ signature:", f->signature(true))); } */ str _doc; if (docstring_options::show_py_signatures_) { _doc += str(const_cast<const char*>(detail::py_signature_tag)); } if (doc != 0 && docstring_options::show_user_defined_) _doc += doc; if (docstring_options::show_cpp_signatures_) { _doc += str(const_cast<const char*>(detail::cpp_signature_tag)); } if(_doc) { object mutable_attribute(attribute); mutable_attribute.attr("__doc__")= _doc; }}BOOST_PYTHON_DECL void add_to_namespace( object const& name_space, char const* name, object const& attribute){ function::add_to_namespace(name_space, name, attribute, 0);}BOOST_PYTHON_DECL void add_to_namespace( object const& name_space, char const* name, object const& attribute, char const* doc){ function::add_to_namespace(name_space, name, attribute, doc);}namespace{ struct bind_return { bind_return(PyObject*& result, function const* f, PyObject* args, PyObject* keywords) : m_result(result) , m_f(f) , m_args(args) , m_keywords(keywords) {} void operator()() const { m_result = m_f->call(m_args, m_keywords); } private: PyObject*& m_result; function const* m_f; PyObject* m_args; PyObject* m_keywords; };}extern "C"{ // Stolen from Python's funcobject.c static PyObject * function_descr_get(PyObject *func, PyObject *obj, PyObject *type_) { if (obj == Py_None) obj = NULL; return PyMethod_New(func, obj, type_); } static void function_dealloc(PyObject* p) { delete static_cast<function*>(p); } static PyObject * function_call(PyObject *func, PyObject *args, PyObject *kw) { PyObject* result = 0; handle_exception(bind_return(result, static_cast<function*>(func), args, kw)); return result; } // // Here we're using the function's tp_getset rather than its // tp_members to set up __doc__ and __name__, because tp_members // really depends on having a POD object type (it relies on // offsets). It might make sense to reformulate function as a POD // at some point, but this is much more expedient. // static PyObject* function_get_doc(PyObject* op, void*) { function* f = downcast<function>(op); list signatures = function_doc_signature_generator::function_doc_signatures(f); if(!signatures) return python::detail::none(); signatures.reverse(); return python::incref( str("\n").join(signatures).ptr()); } static int function_set_doc(PyObject* op, PyObject* doc, void*) { function* f = downcast<function>(op); f->doc(doc ? object(python::detail::borrowed_reference(doc)) : object()); return 0; } static PyObject* function_get_name(PyObject* op, void*) { function* f = downcast<function>(op); if (f->name().ptr() == Py_None) return PyString_InternFromString("<unnamed Boost.Python function>"); else return python::incref(f->name().ptr()); } // We add a dummy __class__ attribute in order to fool PyDoc into // treating these as built-in functions and scanning their // documentation static PyObject* function_get_class(PyObject* /*op*/, void*) { return python::incref(upcast<PyObject>(&PyCFunction_Type)); }}static PyGetSetDef function_getsetlist[] = { {"__name__", (getter)function_get_name, 0, 0, 0 }, {"func_name", (getter)function_get_name, 0, 0, 0 }, {"__class__", (getter)function_get_class, 0, 0, 0 }, // see note above {"__doc__", (getter)function_get_doc, (setter)function_set_doc, 0, 0}, {"func_doc", (getter)function_get_doc, (setter)function_set_doc, 0, 0}, {NULL, 0, 0, 0, 0} /* Sentinel */};PyTypeObject function_type = { PyObject_HEAD_INIT(0) 0, "Boost.Python.function", sizeof(function), 0, (destructor)function_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, //(reprfunc)func_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ function_call, /* tp_call */ 0, /* tp_str */ 0, // PyObject_GenericGetAttr, /* tp_getattro */ 0, // PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT /* | Py_TPFLAGS_HAVE_GC */,/* tp_flags */ 0, /* tp_doc */ 0, // (traverseproc)func_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, //offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ 0, // func_memberlist, /* tp_members */ function_getsetlist, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ function_descr_get, /* tp_descr_get */ 0, /* tp_descr_set */ 0, //offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* 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};object function_object( py_function const& f , python::detail::keyword_range const& keywords){ return python::object( python::detail::new_non_null_reference( new function( f, keywords.first, keywords.second - keywords.first)));}object function_object(py_function const& f){ return function_object(f, python::detail::keyword_range());}handle<> function_handle_impl(py_function const& f){ return python::handle<>( allow_null( new function(f, 0, 0)));}} // namespace objectsnamespace detail{ object BOOST_PYTHON_DECL make_raw_function(objects::py_function f) { static keyword k; return objects::function_object( f , keyword_range(&k,&k)); } void BOOST_PYTHON_DECL pure_virtual_called() { PyErr_SetString(PyExc_RuntimeError, "Pure virtual function called"); throw_error_already_set(); }}}} // namespace boost::python
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?