使用C++编写Python3扩展
时间:2022-07-28
本文章向大家介绍使用C++编写Python3扩展,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Python的很多库中都包含了C/C++的代码,在安装这种库的时候,尝尝会遇到这样的报错:
error: unable to find vcvarsall.bat
通常的解决方案有两种:
- 安装visual studio或者mingw;
- 使用编译好的Python库文件,进行安装。
一般大家都会选择安装编译过的库文件,或者安装mingw,但是如果要在Windows下为自己的Python程序编写扩展,安装visual studio是最优的解决方案。
下面介绍使用C++编写Python扩展模块的常见写法。
传入有限个数据
先建立一个Exten.cpp文件,编写如下代码:
#include "Python.h"
// 函数主体
int add(int a,int b) {
return a + b;
}
// 包裹函数
static PyObject *Exten_add(PyObject *self,PyObject *args) {
int a,b;
// 获取数据,i代表int,ii代表两个int
// 如果没有获取到,则返回NULL
if (!PyArg_ParseTuple(args,"ii",&a,&b)) {
return NULL;
}
return (PyObject*)Py_BuildValue("i",add(a,b));
}
// 添加PyMethodDef ModuleMethods[]数组
static PyMethodDef ExtenMethods[] = {
// add:可用于Python调用的函数名,Exten_add:C++中对应的函数名
{"add",Exten_add,METH_VARARGS},
{NULL,NULL},
};
// 初始化函数
static struct PyModuleDef ExtenModule = {
PyModuleDef_HEAD_INIT,
"Exten",//模块名称
NULL,
-1,
ExtenMethods
};
void PyInit_Exten() {
PyModule_Create(&ExtenModule);
}
再在同文件夹下建立setup.py文件,编写如下代码:
from distutils.core import setup,Extension
MOD = 'Exten' #模块名
setup(name=MOD,ext_modules=[Extension(MOD,sources=['D:\Exten.cpp'])])
然后在CMD控制台输入:
python D:\setup.py build
python D:\setup.py install
此模块便已经安装成功了。可以直接在Python代码中调用:
>>> import Exten
>>> Exten.add(1,3)
4
传入可迭代对象
这种方式只能处理单个数据传入的任务,如果需要处理批量数组等批量数据,则需要涉及到Python对象到C++对象的转化。
以max函数为例,添加max函数之后,还需要为max编写包裹函数,整个Exten文件中代码如下:
#include "Python.h"
#include <vector>
#define INT_MIN -2147483648
using namespace std;
// 函数主体
int add(int a,int b) {
return a + b;
}
int max(vector<int> lst) {
int max_num = INT_MIN;
for (int i =0; i< lst.size(); i++) {
if (lst[i] > max_num) {
max_num = lst[i];
}
}
return max_num;
}
// 包裹函数
static PyObject *Exten_add(PyObject *self,PyObject *args) {
int a,b;
// 如果没有获取到数据
if (!PyArg_ParseTuple(args,"ii",&a,&b)) {
return NULL;
}
return (PyObject*)Py_BuildValue("i",add(a,b));
}
// 模块中每个可供Python调用的函数都需要一个对应的包裹函数
static PyObject *Exten_max(PyObject *self,PyObject *args) {
PyObject *obj;
vector<int> lst;
// O代表对象
if (!PyArg_ParseTuple(args,"O",&obj)) {
return NULL;
}
// 获取可迭代对象
PyObject *iter = PyObject_GetIter(obj);
if (!iter) {
PyErr_SetString(PyExc_TypeError,"The object is not iterable!");
return NULL;
}
while (true) {
// 逐个获取列表中的各个元素
PyObject *next = PyIter_Next(iter);
if (!next) {
break;
}
// 检查是否为long或者long的子类(包括int)
if (!PyLong_Check(next)) {
PyErr_SetString(PyExc_TypeError,"Int or Long list is expected!");
return NULL;
}
// 由Python的Long转化为C/C++的long
long num = PyLong_AsLong(next);
lst.push_back(num);
}
return (PyObject*)Py_BuildValue("i",max(lst));
}
// 添加PyMethodDef ModuleMethods[]数组
static PyMethodDef ExtenMethods[] = {
// add:可用于Python调用的函数名,Exten_add:C++中对应的函数名
{"add",Exten_add,METH_VARARGS},
{"max",Exten_max,METH_VARARGS},
{NULL,NULL},
};
// 初始化函数
static struct PyModuleDef ExtenModule = {
PyModuleDef_HEAD_INIT,
"Exten",//模块名称
NULL,
-1,
ExtenMethods
};
void PyInit_Exten() {
PyModule_Create(&ExtenModule);
}
采取同样的方式build + install之后,就可以使用了:
>>> import Exten
>>> Exten.max([1,2,3,4])
4
>>> Exten.max([1,2,3,4.1])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Int or Long list is expected!
参考:https://blog.csdn.net/baidu_35085676/article/details/79518777
https://stackoverflow.com/questions/22458298/extending-python-with-c-pass-a-list-to-pyarg-parsetuple
https://docs.python.org/3/c-api/long.html
- 动态创建MySQL Group Replication的节点(r11笔记第84天)
- sysbench压测小记(r11笔记第99天)
- WordPress启用memcached动态缓存以及报错解决
- 升级CentOS6.5内核,开启Nginx的fastopen和reuseport特性
- Nginx网站使用CDN之后禁止用户真实IP访问的方法
- 相差数十倍的SQL性能分析(r11笔记第98天)
- shell脚本实现整站缓存和预缓存,进一步提升网站整体加载速度
- Oracle中的PGA监控报警分析(r11笔记第96天)
- MySQL错误修复记录:Table xx is marked as crashed and should be repaired
- WordPress百度自动推送JS优化,规避错误、重复推送问题
- Oracle 12c中DBCA搭建备库体验(r11笔记第92天)
- 一行代码彻底禁用WordPress缩略图自动裁剪功能
- MySQL中xtrabackup备份恢复全攻略(r12笔记第11天)
- 分享一次Linux任务计划crontab不执行的问题排查过程
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- BigData--Hive数据仓库工具
- 读书笔记——《深入浅出 Webpack》( 送 XMind导图和电子书)
- BigData--MapReduce进阶(二)之工作机制
- BigData--MapReduce进阶(一)之框架原理
- BigData--MapReduce入门
- BigData--分布式流数据流引擎Apache Flink
- 【项目实战】ADS 层数据导出
- 前端大杂货铺系列《七》
- BigData--大数据技术之Spark机器学习库MLLib
- 【LeetCode】三数之和
- BigData--大数据技术之SparkStreaming
- Jenkins 入门实战:GitHub Push触发Jenkins自动构建
- 2020最新编辑器集成eslint、prettier、stylelint,git提交预检查代码配置
- eslint+prettier学习
- C++ 友元函数