脚本语言一般使用c等静态语言编写扩展提高性能,下面使用cpp编写一个实现两数之和的python扩展函数
完成案例代码参考:https://1drv.ms/u/s!AquRvPzqx59RjAZ3wk6qpzqEDgF9?e=jZe5hu
构建python环境
减少扩展开发对系统python的影响,建议使用venv创建一个新的python开发环境
virtualenv ~/develop/venvpy3
操作效果如下
使用命令source ~/develop/venvpy3/bin/activate
激活即可
创建扩展文件sumext.cpp
sumext.cpp
#include <iostream>
#include <stdio.h>
#include <Python.h>
using namespace std;
主要是引入依赖的Python.h文件头即可,其它头文件按需引入使用
实现两数相加函数
static PyObject* sum(PyObject* Self, PyObject *args)
{
int a, b, s;
if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
return NULL;
}
s = a + b;
return Py_BuildValue("i", s);
}
这个函数接受两个int类型的参数,有一个int类型的返回值
函数参数解析
PyArg_ParseTuple将python脚本中传入的参数解析为cpp本地数据类型,i表示解析为int类型,两个i:"ii"表示有两个int类型的参数
支持解析的数据类型列表参考:https://docs.python.org/3/c-api/arg.html
函数返回值定义
Py_BuildValue用于将cpp本地数据类型转为python脚本数据类型,i表示将cpp中int类型转为python脚本变量
支持解析的数据类型列表参考:https://docs.python.org/2.0/ext/buildValue.html
定义函数为python扩展函数
static PyMethodDef module_methods[] = {
{"sum", (PyCFunction) sum, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL}
};
定义扩展基础信息
static struct PyModuleDef sumext = {
PyModuleDef_HEAD_INIT,
"sumext",
"extension for add two number",
-1,
module_methods
};
在扩展钩子中注册扩展&扩展函数
PyMODINIT_FUNC PyInit_sumext(void) {
return PyModule_Create(&sumext);
}
PyMODINIT_FUNC PyInit_sum(void) {
return PyModule_Create(&sumext);
}
格式:PyInit_模块名/函数名
作用:python加载模块/模块函数时的初始化函数,可以在模块/函数初始化函数中执行自定义钩子逻辑,最后返回扩展信息sumext即可
编译扩展
setup.py:
from distutils.core import setup, Extension
setup(name='sumext', version='1.0', ext_modules=[Extension('sumext', ['sumext.cpp'])])
然后使用命令python setup.py install
编译,效果参考如下
使用扩展
action.py
import sumext
sum=sumext.sum(1, 2)
print("Sum is :", sum)
然后使用命令python action.py
执行,执行效果如下:
可以看到扩展已经成功加载执行了