Python调用C函数的方法以及如何编写Python的C扩展
时间:2022-05-03
本文章向大家介绍Python调用C函数的方法以及如何编写Python的C扩展,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
01
前言
前言属闲聊,正文请转后。
标题比较长,其实“如何用Python调用C的函数”以及“如何编写Python的C扩展”在广义上是同一件事,因为都是用C写底层实现,用Python作接口。
具体方法有很多,比如用ctypes、用SWIG等等,各种方法有利有弊。前段时间笔者用SWIG编译某小段函数一直出BUG,检查了两天才发现原来是因为MinGW 32-bit和Python 64-bit不兼容,加之后续笔者还需要用到NumPy C-API,所以现在笔者已弃坑SWIG,转用以下方法:
- 按照Python C-API的编程规范,用C编写底层实现函数。
- 用Python自带的disutils模块来管理编译、打包、生成Python模块。
所以后续的内容将主要围绕以上的方法来展开。
02
正文
编写C代码
假设要实现一个数学计算模块mymath,包含一个整数加法的函数add,那么首先要编写以下代码:
#include "D:Anaconda2includePython.h"
/* file: mymath.c *
/// 真正实现
int add(int a, int b)
{
return a + b; }
// 包装函数。Python调用add方法时传进来的参数在args里
PyObject* wrap_add(PyObject* self, PyObject* args)
{
int a, b, result;
// 解析参数 if (!PyArg_ParseTuple(args, "ii", &a, &b))
return NULL; result = add(a, b);
// 返回PyObject* 类型的参数 return Py_BuildValue("i", result); }
// mymath模块所包含的函数列表
static PyMethodDef mymathMethods[] = {
// 每行一个方法,含义依次为 // Python方法名,C方法名,参数值,方法文档 {"add", wrap_add, METH_VARARGS, "doc: add(a, b) nreturn a + b"},
{NULL, NULL, 0, NULL}
// 上面的最后一行相当于结束符};// 初始化模块的方法,自动调用
// 命名要求为init后加上模块名
void initmymath()
{ PyObject* m;
// 调用Py_InitModule方法初始化模块mymath,其中模块所具有 // 的函数列表由第二个参数提供 m = Py_InitModule("mymath", mymathMethods);
}
编译、打包与生成
在与mymath.c文件同级目录下编写setup.py文件,代码如下:
# file: setup.pyfrom distutils.core import setup, Extension module1 = Extension('mymath', sources = ['mymath.c']) setup(name = 'mymath', version = '1.0', description = 'This is a Math package', ext_modules= [module1])
然后打开命令行窗口,进入到mymath.c所在目录,输入以下命令:
python setup.py build
可以看到以下输出信息:
编译、打包、生成时的输出信息.png
这个时候可以看到当前目录多了个build文件夹,一路进去可以看到mymath.pyd文件,这就是直接可调用的Python module了。继续在命令行里进入Python,可以直接调用mymath模块了。
调用效果
03
参考资料
[1] Python/C API Reference Manual, https://docs.python.org/2/c-api/
[2] 《Python基础教程》(第2版)
- 干货,比较全面的c#.net公共帮助类(Common.Utility)
- Linux中如何恢复rm命令误删除的文件之extundelete编译安装及使用
- JDK1.7 安装加(一劳永逸的环境配置)
- Jquery 遍历数组之$().each方法与$.each()方法介绍
- ExtJs学习笔记(2)_Basic GridPanel[基本网格]
- Jquery 遍历数组之grep()方法介绍
- ExtJs学习笔记(1)_Hello World!
- Jquery filter()方法简介
- 加拿大滑铁卢大学刘腾博士:平行增强学习及其无人驾驶应用
- 曾六位数被秒的yadea.com 终端真是雅迪!
- 2018年IT行业必须面对的7个改变
- SqlTransaction 数据库编程事务使用示例
- 再谈web.config/app.config敏感数据加/解密的二种方法
- NVIDIA颁布最新禁令,GeForce不能再行深度学习了!
- 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 数组属性和方法
- 使用Python-OpenCV消除图像中孤立的小区域操作
- PHP实现数组和对象的相互转换操作示例
- PHP单元测试框架PHPUnit用法详解
- PHP5中使用mysqli的prepare操作数据库的介绍
- php中的explode()函数实例介绍
- ThinkPHP5.0框架验证码功能实现方法【基于第三方扩展包】
- PHP的mysqli_rollback()函数讲解
- PHP中十六进制颜色与RGB颜色值互转的方法
- PHP后台备份MySQL数据库的源码实例
- PHP的PDO连接讲解
- PHP生成指定范围内的N个不重复的随机数
- 实例讲解通过PHP创建数据库
- PHP的mysqli_select_db()函数讲解
- PHP的PDO事务与自动提交
- 使用pytorch实现论文中的unet网络