栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

从Cython传递闭包到C ++

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

从Cython传递闭包到C ++

我相信您的目标是将可调用的Python对象传递给接受的对象

std::function
。您需要创建一些C ++代码来实现它,但这相当简单。

从尽可能简单地定义“ accepts_std_function.hpp”开始,以提供一个说明性示例:

#include <functional>#include <string>inline void call_some_std_func(std::function<void(int,const std::string&)> callback) {    callback(5,std::string("hello"));}

然后,诀窍是创建一个包含

PyObject*
和的包装器类
operator()
。定义
operator()
允许将其转换为
std::function
。大部分班级只是口算。“
py_obj_wrapper.hpp”:

#include <Python.h>#include <string>#include "call_obj.h" // cython helper fileclass PyObjWrapper {public:    // constructors and destructors mostly do reference counting    PyObjWrapper(PyObject* o): held(o) {        Py_XINCREF(o);    }    PyObjWrapper(const PyObjWrapper& rhs): PyObjWrapper(rhs.held) { // C++11 onwards only    }    PyObjWrapper(PyObjWrapper&& rhs): held(rhs.held) {        rhs.held = 0;    }    // need no-arg constructor to stack allocate in Cython    PyObjWrapper(): PyObjWrapper(nullptr) {    }    ~PyObjWrapper() {        Py_XDECREF(held);    }    PyObjWrapper& operator=(const PyObjWrapper& rhs) {        PyObjWrapper tmp = rhs;        return (*this = std::move(tmp));    }    PyObjWrapper& operator=(PyObjWrapper&& rhs) {        held = rhs.held;        rhs.held = 0;        return *this;    }    void operator()(int a, const std::string& b) {        if (held) { // nullptr check  call_obj(held,a,b); // note, no way of checking for errors until you return to Python        }    }private:    PyObject* held;};

该文件使用非常短的Cython文件来完成从C ++类型到Python类型的转换。“ call_obj.pyx”:

from libcpp.string cimport stringcdef public void call_obj(obj, int a, const string& b):    obj(a,b)

然后,您只需要创建包装这些类型的Cython代码即可。编译该模块并调用

test_func
以运行它。(“ simple_version.pyx” :)

cdef extern from "py_obj_wrapper.hpp":    cdef cppclass PyObjWrapper:        PyObjWrapper()        PyObjWrapper(object) # define a constructor that takes a Python object  # note - doesn't match c++ signature - that's fine!cdef extern from "accepts_std_func.hpp":    void call_some_std_func(PyObjWrapper) except + # here I lie about the signature # because C++ does an automatic conversion to function pointer # for classes that define operator(), but Cython doesn't know thatdef example(a,b):    print(a,b)def test_call():    cdef PyObjWrapper f = PyObjWrapper(example)    call_some_std_func(f)

上面的版本可以使用,但是在一定程度上受到限制,因为如果您想使用其他

std::function
专门化的方法来做,则需要重写其中的一些(并且从C
++到Python类型的转换自然不会适合模板实现)。一种简单的解决方法是使用Boost Python库
object
类,该类具有templated
operator()
。这是以引入额外的库依赖性为代价的。

首先定义标头“
boost_wrapper.hpp”以简化从

PyObject*
到的转换
boost::python::object

#include <boost/python/object.hpp>inline boost::python::object get_as_bpo(PyObject* o) {    return boost::python::object(boost::python::handle<>(boost::python::borrowed(o)));}

然后,您只需使用Cython代码包装此类(“ boost_version.pyx”)。再说一次

test_func

cdef extern from "boost_wrapper.hpp":    cdef cppclass bpo "boost::python::object":        # manually set name (it'll conflict with "object" otherwise        bpo()    bpo get_as_bpo(object)cdef extern from "accepts_std_func.hpp":    void call_some_std_func(bpo) except + # again, lie about signaturedef example(a,b):    print(a,b)def test_call():    cdef bpo f = get_as_bpo(example)    call_some_std_func(f)

一个“ setup.py”

from distutils.core import setup, Extensionfrom Cython.Build import cythonizeextensions = [    Extension("simple_version", # the extension namesources=["simple_version.pyx", "call_obj.pyx" ],language="c++",  # generate and compile C++ pre      ),    Extension("boost_version", # the extension namesources=["boost_version.pyx"],libraries=['boost_python'],language="c++",  # generate and compile C++ pre      )    ]setup(ext_modules = cythonize(extensions))

(最后一种选择是用于

ctypes
从可调用的Python生成C函数指针。请参见使用不带gil的类的方法的函数指针(答案的下半部分)和http://osdir.com/ml/python-cython- devel /
2009-10 / msg00202.html。我在这里不做详细介绍。)



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/641393.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号