Python调用C函数的方法以及如何编写Python的C扩展

正文共1535个字,2张图,预计阅读时间4分钟。


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:\Anaconda2\include\Python.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版)


原文链接:https://www.jianshu.com/p/cd28e8b0cce1


查阅更为简洁方便的分类文章以及最新的课程、产品信息,请移步至全新呈现的“LeadAI学院官网”:

www.leadai.org


请关注人工智能LeadAI公众号,查看更多专业文章

大家都在看

零基础入门深度学习 | 第一章:感知器

零基础入门深度学习 | 第二章:线性单元和梯度下降

零基础入门深度学习 | 第四章:卷积神经网络

最全常见算法工程师面试题目整理(一)

最全常见算法工程师面试题目整理(二)

透析 | 卷积神经网络CNN究竟是怎样一步一步工作的?

用Python给头像加上圣诞帽

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值