C、C++ 和 Python 是我最喜欢的语言。C 和 C++ 提供了性能(当然,两者之间存在很大差异),而 Python 提供了简单性和快速的开发速度。将它们混合使用可以将两者的优势融入到我们的开发环境中。

它们之间的关系可以是双向的

  • 扩展 Python 是一个创建用 C 或 C++ 编写的 Python 扩展的过程,这些扩展以共享库的形式存在(win 中为 .pyd,nix 中为 .so),可以从 Python 环境中导入和执行。这些二进制原生扩展通常包含性能关键代码,以及以前在 C/C++ 库中实现的功能,这些功能希望暴露给 Python 环境。

  • 嵌入 Python 是一个创建原生应用程序的过程,该应用程序是用 C 或 C++ 开发的,可以使用 Python 解释器执行 Python 代码。

这两项任务都可以在“低级”使用例如 CPython 的 Python/C API 来实现,但也存在许多 第三方 工具试图改进此过程。

Boost 可能是世界上最知名的 C++ 库,多年来一直推动着 C++ 的发展。它具有一个 Boost.Python 库,旨在为扩展和嵌入 Python 提供高级 C++ 抽象。然而,在我看来,它存在一些缺点,一个重要的缺点是难以构建(它不是仅限于头的,像许多其他 Boost 库一样)。它使用 b2 Boost 构建系统,我不太习惯,而且使用其他构建系统也不简单。此外,它的活动和维护似乎也可能更大。

进入 pybind11

我通常会使用 Boost,但在其他工具中,pybind11 非常引人注目。它在 Github 上获得了近 1000 颗星,是一个非常活跃的项目,并更新到最新的 C++ 编译器和功能。此外,它是一个基于 TMP 的库,仅限于头文件,这大大提高了可用性。您可以在 文档中阅读一些基准测试

入门

使用 pybind11 入门非常简单。我创建了一个 Conan 包,但由于它仅限于头文件,因此只需克隆源代码并指向包含目录即可轻松使用它。

要构建第一个应用程序,请获取示例

$ git clone https://github.com/memsharded/pybind11-example.git
$ cd pybind11-example

有一个简单的 conanfile.txt,它告诉 Conan 获取 Conan pybind11 包并为我们方便地生成一个 CMake 文件

[requires]
pybind11/1.4@memsharded/stable

[generators]
cmake

Hello world Python/C++ 应用程序

我们只是使用了 pybind11 帮助中提供的代码,一个简单的整数加法插件,在一个名为 example.cpp 的文件中。

#include <pybind11/pybind11.h>

int add(int i, int j) {
    return i + j;
}

namespace py = pybind11;

PYBIND11_PLUGIN(example) {
    py::module m("example", "pybind11 example plugin");
    m.def("add", &add, "A function which adds two numbers");
    return m.ptr();
}

我们将使用 CMake 构建扩展,使用提供的 CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

project(example)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
include_directories(SYSTEM ${CONAN_INCLUDE_DIRS})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})

... 

对原始 CMakeLists.txt 进行的唯一更改是定义 pybind11 头文件的包含目录,并将输出目录定义为当前目录,以便我们的扩展位于当前文件夹中。

我们将使用 Visual Studio 14 构建扩展。请注意,即使是官方的 Python 版 VS 也是(旧的)VS2008,也可以使用更现代的编译器创建此类扩展。参数必须与您的编译器和 Python 安装相匹配。请注意,扩展架构必须与您的 Python 架构相匹配,因此如果您有 32 位 Python,请使用“Visual Studio XX”,如果您有 64 位 Python,则可能需要“Visual Studio XX Win64”。

$ mkdir build && cd build
# Retrieve the pybind package
$ conan install ..
$ cmake .. -G "Visual Studio 14" -DPYTHON_INCLUDE_DIR="C:/Python27/include" -DPYTHON_LIBRARY="C:/Python27/libs/python27.lib"
$ cmake --build . --config Release

在 Linux 中,您可以使用以下命令构建它,它可能会自动找到 Python,但请检查 CMake 输出以确保它找到了您想要的 Python 发行版。

$ cmake .. -DCMAKE_BUILD_TYPE=Release
$ cmake --build .

就是这样,我们已经准备好可以使用 Python 的扩展了。

$ python
>>> import example
>>> example.add(2, 3)
5L

结论

我发现 pybind11 优雅、易于使用、高效,而且非常重要,我也喜欢它定义扩展的语法。总而言之,这是一项非常棒的工作。它唯一的缺点可能是它似乎不是嵌入 Python 的工具(我可能错了)。我也有信心该项目非常活跃,并得到社区的支持,因此在我看来,这可能是扩展 Python 的最佳选择。

我将在几天后在布里斯托尔的 Accu 会议 上讨论这些主题,也许 在那里见? :) 您也可以 关注我的 X 以获取有关 C/C++/Python 和通用编程的推文。