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