0

0

c++ 编写python扩展 c++如何为python编写c++模块

星降

星降

发布时间:2026-03-17 21:28:55

|

104人浏览过

|

来源于php中文网

原创

<p>最不踩坑的结论是:用 pybind11 而非手写 PyInit_* 和 PyModuleDef;它自动处理类型映射、模块导出、ABI 兼容性,避免 ImportError、undefined symbol 等常见错误,且需严格匹配模块名、文件名与 PYBIND11_MODULE 宏。</p>

c++ 编写python扩展 c++如何为python编写c++模块

用 pybind11 写 Python 扩展最不踩坑

直接结论:别手写 PyInit_*PyModuleDef,用 pybind11 —— 它把 C++ 类型、函数、异常、STL 容器的映射全包了,且编译链干净,比原生 C API 少写 80% 模板代码。

常见错误现象:ImportError: dynamic module does not define init function(老式 Python 2 风格初始化没适配 Py3.8+)、undefined symbol: _Py_ZeroStruct(链接时漏了 -lpython3.x 或用了系统 Python 而非 venv 中的)。

  • 必须用 pybind11_add_module() CMake 函数(不是 add_library(... SHARED) 手动设),它自动处理导出符号、Python ABI 兼容性、PYBIND11_MODULE 宏展开
  • 模块名必须和文件名一致(mylib.cppPYBIND11_MODULE(mylib, m)import mylib),否则 ImportError: No module named 'xxx'
  • 如果 C++ 里抛 std::runtime_error,默认转成 RuntimeError;想映射成特定 Python 异常(如 ValueError),得用 m.attr("ValueError") = py::eval("ValueError") + throw py::value_error("...")

如何暴露 std::vector 和 numpy 数组互操作

这是性能关键点:Python 用户传 list 还是 np.ndarray?C++ 函数该接什么?不统一就频繁拷贝,一调用慢 10 倍。

使用场景:图像处理、数值计算、模型推理等需要零拷贝传递大内存块的场合。

立即学习Python免费学习笔记(深入)”;

  • 暴露 std::vector<float> 给 Python,默认转成 list(深拷贝);加 .def_readwrite("data", &MyClass::vec, py::return_value_policy::reference) 才能返回引用(但注意生命周期!Python 持有后 C++ 对象不能析构)
  • 要支持 numpy.ndarray 输入,用 pybind11/numpy.h,声明参数为 py::array_t<float>;调用 .request() 拿到 buffer_info,再用 static_cast<float*>(buf.ptr) 直接访问内存
  • 返回 py::array_t<int> 时,用 py::array_t<int>(shape, data_ptr, parent) 构造,传入 C++ 堆内存指针 + parent=py::cast(self) 防止提前释放

Windows 下编译失败:LNK2001 / unresolved external symbol PyInit_*

根本原因不是代码写错,而是构建系统没按 Python DLL 导出规则生成模块入口。

ARTi.PiCS
ARTi.PiCS

ARTi.PiCS是一款由AI驱动的虚拟头像生产器,可以生成200多个不同风格的酷炫虚拟头像

下载

参数差异:pybind11 在 Windows 上默认生成 .pyd(本质是 DLL),但要求导出函数名为 PyInit_mymodule,且必须用 /EXPORT:PyInit_mymodule 显式导出(MSVC)或 -Wl,--export-all-symbols(MinGW)。

  • CMakeLists.txt 里不能只写 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ...),必须加 set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)(MSVC)或手动写 target_link_options(... PRIVATE "/EXPORT:PyInit_mymodule")
  • 确保 Python 解释器路径和链接的 python3x.lib 匹配:用 python -c "import sysconfig; print(sysconfig.get_paths()['stdlib'])" 确认 Python 版本,再查 lib/python3.x/config-3.x-x86_64-linux-gnu/libpython3.x.so(Linux)或 libs/python3x.lib(Windows)
  • VS 编译时关掉 /GL(全程序优化),它会把 PyInit_* 内联掉导致导出失败

调试段错误:Python 进程在 C++ 模块里 crash

这类问题最难定位,因为 Python 的 traceback 不显示 C++ 栈,gdb 里又卡在 PyObject_Call 里。

性能影响:加日志会掩盖竞态,用 printf 可能因缓冲不刷屏;用 PyErr_SetString 又得手动清异常栈。

  • 先开 core dump:ulimit -c unlimited + gdb python core,然后 bt full 看 C++ 函数参数和局部变量值
  • 在 C++ 函数开头加 if (!PyGILState_Check()) { PyErr_SetString(PyExc_RuntimeError, "GIL not held"); return nullptr; },避免多线程调用时 GIL 丢失
  • 检查所有 py::object 是否来自同一 Python 解释器实例(嵌入式场景易出错);跨线程传递 py::object 必须用 py::reinterpret_borrow<py::object>(obj) + 手动管理引用计数

最常被忽略的是:C++ 模块里调用的第三方库(比如 OpenCV)是否和 Python 使用的同一套 CRT(Windows)或 libc(Linux)。混用会导致内存分配器不一致,free() 一个 new 出来的指针,当场崩。

相关文章

python速学教程(入门到精通)
python速学教程(入门到精通)

python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
python中print函数的用法
python中print函数的用法

python中print函数的语法是“print(value1, value2, ..., sep=' ', end=' ', file=sys.stdout, flush=False)”。本专题为大家提供print相关的文章、下载、课程内容,供大家免费下载体验。

193

2023.09.27

python print用法与作用
python print用法与作用

本专题整合了python print的用法、作用、函数功能相关内容,阅读专题下面的文章了解更多详细教程。

19

2026.02.03

css中float用法
css中float用法

css中float属性允许元素脱离文档流并沿其父元素边缘排列,用于创建并排列、对齐文本图像、浮动菜单边栏和重叠元素。想了解更多float的相关内容,可以阅读本专题下面的文章。

597

2024.04.28

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

108

2025.10.23

typedef和define区别
typedef和define区别

typedef和define区别在类型检查、作用范围、可读性、错误处理和内存占用等。本专题为大家提供typedef和define相关的文章、下载、课程内容,供大家免费下载体验。

120

2023.09.26

define的用法
define的用法

define用法:1、定义常量;2、定义函数宏:3、定义条件编译;4、定义多行宏。更多关于define的用法的内容,大家可以阅读本专题下的文章。

393

2023.10.11

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

847

2023.08.22

printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

76

2023.06.20

抖漫入口地址合集
抖漫入口地址合集

本专题整合了抖漫入口地址相关合集,阅读专题下面的文章了解更多详细地址。

17

2026.03.17

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 11.5万人学习

C 教程
C 教程

共75课时 | 5.6万人学习

C++教程
C++教程

共115课时 | 22.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号