美文网首页
python 调用 C++ so

python 调用 C++ so

作者: leon_tly | 来源:发表于2022-12-08 13:51 被阅读0次

    python使用C++生成的so的两种方式

    ctypes

    import ctypes
    so = ctypes.cdll.LoadLibrary
    lib = so("./libactAnalyze.so")
    actAnalyze = lib.actAnalyze
    #指定调用接口的入口参数类型
    actAnalyze.argtypes = [ctypes.c_char_p, ctypes.c_int]
    #指定调用接口的返回值类型
    actAnalyze.restype = ctypes.c_char_p
    buff = 'test'
    # char* 类型入口参数,通过bytes(buff,"utf8")传入
    #返回值为char*, 通过ctypes.string_at()方法获取到bytes类型字符串
    ctypes.string_at(actAnalyze(bytes(buff,"utf8")))
    

    pybind11

    函数

    #include <pybind11/pybind11.h>
    
    int add(int i, int j) {
        return i + j;
    }
    
    PYBIND11_MODULE(example, m) {
        m.doc() = "pybind11 example plugin"; // optional module docstring
    
        m.def("add", &add, "A function that adds two numbers");
    }
    

    PYBIND11_MODULE()宏创建一个函数,当从 Python 中import时将调用该函数。模块名称(example)作为第一个宏参数给出(不能用引号引起来)。第二个参数(m)定义了一个 py::module_ 类型的变量,它是创建绑定的主接口。方法 module_::def() 生成将 add()函数公开给 Python 的绑定代码。

    函数绑定关键字参数

    // 常规
    m.def("add", &add, "A function which adds two numbers",
          py::arg("i"), py::arg("j"));
    // 简约
    using namespace pybind11::literals;
    m.def("add2", &add, "i"_a, "j"_a);
    

    arg 是几个特殊的标记类之一,可用于将元数据传递到 module_::def()。有了这个修改后的绑定代码,我们现在可以使用关键字参数调用函数,这是一个更具可读性的替代方案,特别是对于采用许多参数的函数

    默认参数

    int add(int i = 1, int j = 2) {
        return i + j;
    }
    
    m.def("add", &add, "A function which adds two numbers",
          py::arg("i") = 1, py::arg("j") = 2);
    
    // 简约
    m.def("add2", &add, "i"_a=1, "j"_a=2);
    

    pybind11无法自动提取函数中的默认参数,可以通过arg直接指定。

    自定义类型

    struct Pet {
        Pet(const std::string &name) : name(name) { }
        void setName(const std::string &name_) { name = name_; }
        const std::string &getName() const { return name; }
    
        std::string name;
    };
    
    #include <pybind11/pybind11.h>
    
    namespace py = pybind11;
    
    PYBIND11_MODULE(example, m) {
        py::class_<Pet>(m, "Pet")
            .def(py::init<const std::string &>())
            .def("setName", &Pet::setName)
            .def("getName", &Pet::getName);
    }
    

    class_为C++类或结构样式的数据结构创建绑定。init()是一个便利的函数,它将构造函数的参数类型作为模板参数,并包装相应的构造函数。

    py::class_<Pet>(m, "Pet")
        .def(py::init<const std::string &>())
        .def("setName", &Pet::setName)
        .def("getName", &Pet::getName)
        .def("__repr__",
            [](const Pet &a) {
                return "<example.Pet named '" + a.name + "'>";
            }
        );
    

    包装__repr__函数,替换默认打印的东西

    py::class_<Pet>(m, "Pet")
        .def(py::init<const std::string &>())
        .def_readwrite("name", &Pet::name)
        // ... remainder ...
    

    使用class_::def_readwrite包装public 成员变量name,可以直接修改变量值。class_::def_readonly()可以用来包装const变量。

    class Pet {
    public:
        Pet(const std::string &name) : name(name) { }
        void setName(const std::string &name_) { name = name_; }
        const std::string &getName() const { return name; }
    private:
        std::string name;
    };
    
    py::class_<Pet>(m, "Pet")
        .def(py::init<const std::string &>())
        .def_property("name", &Pet::getName, &Pet::setName)
    

    class_::def_property()(class_::def_property_readonly()用于只读数据)可用于在Python中提供类似字段的接口,该接口将透明地调用setter和getter函数。

    相关文章

      网友评论

          本文标题:python 调用 C++ so

          本文链接:https://www.haomeiwen.com/subject/tvmwfdtx.html