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

python 调用 C++ so

作者: leon0514 | 来源:发表于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