pybind11中文资料(第四章 第一步)
在此我要特别感谢pybind11项目创立者Wenzel Jakob以及众多项目参与者4 第一步本节演示了pybind11的基本功能。在开始之前,请确保已设置开发环境并编译测试用例集。4.1 编译测试用例4.1.1Linux/MacOSLinux系统,需要安装python-dev或python3-dev软件包以及cmake。Mac OS,包含的python版本可直接使用,但仍然...
在此我要特别感谢pybind11项目创立者 Wenzel Jakob以及众多项目参与者
4 第一步
本节演示了pybind11的基本功能。在开始之前,请确保已设置开发环境并编译测试用例集。
4.1 编译测试用例
4.1.1Linux/MacOS
Linux系统,需要安装python-dev或python3-dev软件包以及cmake。Mac OS,包含的python版本可直接使用,但仍然必须安装cmake。
安装必备组件后,执行
mkdir build
cd build
cmake ..
make check -j 4
最后一行将编译并且运行测试
4.1.2windows
Windows上,仅支持Visual Studio 2015及更高版本,因为pybind11依赖于各种C ++ 11语言功能,而这些特性会破坏旧版本的Visual Studio。
编译并运行测试
mkdir build
cd build
cmake ..
cmake --build . --config Release --target check
这将完全用命令行,创建一个Visual Studio项目,编译并运行目标。
Note:
如果所有测试都失败,请确保python二进制文件和测试用例在相同的处理器类型和系统位宽(i386或x86_64)编译。你可用cmake -A x64 .. 命令指定x86_64作为Visual Studio项目的体系结构。
See also:
熟悉Boost.Python的高级用户可能希望跳过教程并查看test目录中的测试用例,该测试用例运用了pybind11的所有特性。
4.2头文件和命名空间约定
为简洁起见,所有代码示例都假定存在以下两行:
#include <pybind11/pybind11.h>
namespace py = pybind11;
某些功能可能需要其他头文件,但会根据需要指定。
4.3为简单函数创建绑定
首先从为一个简单的函数创建Python绑定开始,函数计算两个数字之和并返回的结果:
int add(int i, int j) {
return i + j;
}
为简单起见[1],这个函数和绑定代码放在example.cpp文件中,文件内容如下:
#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 which adds two numbers");
}
[1]实际上,实现和绑定代码通常位于单独的文件中。
PYBIND11_MODULE()宏创建了一个函数,当Python代码import相应模块时将调用该函数。模块名(example)作为第一个宏参数给出(不需要用引号包含)。第二个参数(m)定义了一个py::module类型的变量,它是创建绑定的主要接口。方法module::def()将生成add()函数的Python的绑定代码。
Note:
注意到只要少量的代码就可以将函数暴露给Python:所有跟函数入参和返回值的细节由模板元编程自动推断。这种方法和语法是从Boost.Python中借用的,尽管底层实现是完全不同的。
pybind11是一个只有头文件的库,因此没有必要链接任何特殊的库,也没有中间转换步骤。在Linux系统中,可以使用以下命令编译上面的示例:
$ c++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` example.cpp ˓→-o example`python3-config --extension-suffix`
如果需要更多有关于Linux和MacOS上所需编译标志的详细信息,请参阅手动构建。有关完整的跨平台编译说明,请参阅 构建系统 页面。
该python_example和cmake_example库也是很适合初学者的。它们都是具有跨平台构建系统的完整项目示例。两者之间的唯一区别是python_example使用Python的setuptools构建模块,而cmake_example使用CMake(这应该是已有的C ++项目的首选)。
构建上述C ++代码将生成可导入Python的二进制模块文件。假设已编译的模块位于当前目录中,以下交互式Python会话将显示如何加载和执行该示例:
$ python
Python 2.7.10 (default, Aug 22 2015, 20:33:39)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
>>> example.add(1, 2)
3L
>>>
4.4关键字参数
只要对代码稍加改动,就可以通知Python有关参数的名称(例如本例中的“i”和“j”)。
m.def("add", &add, "A function which adds two numbers",
py::arg("i"), py::arg("j"));
arg是可用于将元数据传递到module::def()的几个特殊标记类之一。使用这个修改后的绑定代码,我们可以使用关键字参数来调用函数,这更具可读性,特别是带有许多参数的函数。
>>> import example
>>> example.add(i=1, j=2)
3L
关键字名称也出现在文档中的函数签名中。
>>> help(example)
....
FUNCTIONS
add(...)
Signature : (i: int, j: int) -> int
A function which adds two numbers
还可以使用较短的命名参数表示法:
// regular notation
m.def("add1", &add, py::arg("i"), py::arg("j"));
// shorthand
using namespace pybind11::literals;
m.def("add2", &add, "i"_a, "j"_a);
_a后缀形成C++11字面量就相当于arg。请注意,这种操作必须首先声明using namespace pybind11::literals。除了literals,这不会从命名空间内引入其他内容。
4.5默认参数
现在假设要绑定的函数具有默认参数,例如:
int add(int i = 1, int j = 2) {
return i + j;
}
不巧的是,pybind11无法自动提取这些参数,因为它们不是函数类型信息的一部分。但是,使用以下arg来指定它们:
m.def("add", &add, "A function which adds two numbers",
py::arg("i") = 1, py::arg("j") = 2);
默认值也出现在文档中。
>>> help(example)
....
FUNCTIONS
add(...)
Signature : (i: int = 1, j: int = 2) -> int
A function which adds two numbers
简写符号也可用于默认参数:
// regular notation
m.def("add1", &add, py::arg("i") = 1, py::arg("j") = 2);
// shorthand
m.def("add2", &add, "i"_a=1, "j"_a=2);
4.6导出变量
为了暴露C++变量,需要使用attr函数在模块中注册它,做法如下。内置类型和常规对象(稍后将详细介绍)在分配为属性时会自动转换,并且可以使用py::cast函数显式转换。
PYBIND11_MODULE(example, m) {
m.attr("the_answer") = 42;
py::object world = py::cast("World");
m.attr("what") = world;
}
然后可以从Python访问这些变量
>>> import example
>>> example.the_answer
42
>>> example.what
'World'
4.7支持的数据类型
原生支持大量数据类型,可以无缝地用作函数参数,通常直接返回值或者经过py::cast处理再返回。有关完整概述,请参阅类型转换部分。
更多推荐
所有评论(0)