安装
开始之前,需要用 pip 安装 cppimport,在终端或命令提示符中执行:
pip install cppimport
快速示例
下面通过一个简单示例,展示如何利用 cppimport 和 pybind11 直接从 Python 中导入并使用 C++ 文件。
创建 C++ 代码
首先,创建一个名为 somecode.cpp 的 C++ 文件,写入以下代码:
// cppimport
#include <pybind11/pybind11.h>
namespace py = pybind11;
int square(int x) {
return x * x;
}
PYBIND11_MODULE(somecode, m) {
m.def("square", &square);
}
/*
<%
setup_pybind11(cfg)
%>
*/
导入并使用 C++ 代码
现在,在 Python 解释器中导入这个 C++ 扩展:
import cppimport.import_hook
import somecode
# 从 Python 调用 C++ 函数
somecode.square(9)
你会看到输出 81,说明 C++ 函数 square 已经被成功调用。就这样,通过 cppimport 和 pybind11 将 C++ 代码集成到了 Python 中。
详细解析
顶部的注释
// cppimport 这行注释至关重要,它告诉 cppimport 需要将随后的代码片段编译为 Python 扩展模块并导入。缺少该注释,cppimport 就不会把这些代码视作可导入的扩展。
主要逻辑
C++ 代码的核心应类似标准的 pybind11 扩展模板:引入 pybind11 头文件,并定义要在 Python 中暴露的函数(如 square)。
配置块
在 somecode.cpp 文件末尾,有一个配置块:
/*
<%
setup_pybind11(cfg)
%>
*/
构建过程中,cppimport 会把这部分当作 Python 代码来执行,方便你指定编译器、链接器参数、依赖等配置细节,以满足编译需求。
生产环境构建
在生产环境中,你可能不想每次手动编译 C++ 代码。针对这一问题,cppimport 提供了命令行预编译工具:
python -m cppimport build
该命令会编译当前目录及其子目录下所有包含 // cppimport 注释的 .c 和 .cpp 文件(前提是配置已正确设置)。
生产环境优化
跳过校验码和二进制存在检查
为了提升启动性能,可以配置 cppimport 跳过这些检查:
cppimport.settings['release_mode'] = True
警告:在发布模式下务必确保所有必需的二进制文件已预编译,否则导入缺失的文件会抛出异常。
常见问题
到底发生了什么?
cppimport 简化了将 C++ 功能集成进 Python 应用的流程,自动化了编译步骤,允许你同时编辑 Python 和 C++ 文件而无需手动重新编译,极大提升了开发效率。
cppimport 每次导入模块时都会重新编译吗?
只在首次导入时编译。之后的导入不会重新编译,但会检查 C++ 源文件或依赖项是否变化,以保证模块是最新状态。
如何在一个扩展中使用多个源文件?
可以在配置块中通过 cfg['sources'] 列出多个源文件。
如何强制重新编译,即使校验码匹配?
通过以下设置实现:
cppimport.settings['force_rebuild'] = True
能否获取更详细的输出信息?
可以,通过配置日志输出获得更多信息,比如给根日志程序或 cppimport 日志程序添加处理器。
如何强制重新编译,无论校验码如何?
在配置中或直接在 Python 代码里将 force_rebuild 设为 True 即可。
总结
cppimport 是一个强大的工具,让您能直接从 Python 导入 C++ 文件,提升性能并改善工作流效率。结合 pybind11 和 cffi 的能力,开发者可以直接在 Python 中集成已有的 C/C++ 库或编写关键性能函数,从而提升应用性能与开发效率。
项目地址:https://github.com/tbenthompson/cppimport
更多关于 Python 与 C++ 混合编程的实践交流,欢迎访问 云栈社区。