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函数。
网友评论