文档章节

python的c语言扩展方法简介

openthings
 openthings
发布于 2015/01/21 09:28
字数 1513
阅读 1115
收藏 2

原文地址:[http://www.isnowfy.com/introduction-to-python-c-extension/

python是一门非常方便的动态语言,很多你用c或者java要很多行的代码,可能python几行就搞定了,所以python社区一直有个口号 “人生苦短,我用python”,但是方便至于,也带来速度上的问题。python最被人诟病的就是程序的运行速度了,所以结合c的快速和python的 方便,就诞生了很多解决方案。首先注意到python就是c写成的,所以最根本的解决方案就是利用原生的python c api来写c程序,然后编译成链接库文件(linux下就是so文件),然后在python中直接调用,而且其他的解决方案也基本是围绕这个思路,只不过 替你做了很多重复的工作。这次主要是简要介绍下python c apiswig,sip,ctypescythoncffi的使用。


python c api

首先来看最原始的就是使用python c api了。

  1. #include <Python.h>

  2.  

  3. static PyObject* add(PyObject* self, PyObject* args){

  4.     int a = 0;

  5.     int b = 0;

  6.     if(!PyArg_ParseTuple(args, "i|i", &a, &b))

  7.         return NULL;

  8.     return Py_BuildValue("i", a+b);

  9. }

  10.  

  11. static PyObject* sub(PyObject* self, PyObject* args){

  12.     int a = 0;

  13.     int b = 0;

  14.     if(!PyArg_ParseTuple(args, "i|i", &a, &b))

  15.         return NULL;

  16.     return Py_BuildValue("i", a-b);

  17. }

  18.  

  19. static PyMethodDef addMethods[]={

  20.     {"add", add, METH_VARARGS},

  21.     {"sub", sub, METH_VARARGS},

  22.     {NULL, NULL, 0, NULL}

  23. };

  24.  

  25. void initmytest(){

  26.     Py_InitModule("mytest", addMethods);

  27. }

首先是引入Python.h这个头文件,所以编译的时候要注意引入python的库,python中的对象在c中都是用PyObject来表示的, 程序中定义了add和sub两个方法,然后编写init函数,名字注意是init加上你的module的名字,然后调用Py_InitModule函数来 告诉python你定义的函数有哪些。然后就是把他编译成so文件。

  1. gcc mytest.c -shared -lpython2.7 -L /usr/lib/python2.7/ -I /usr/include/python2.7/ -o mytest.so

这样你就可以在python中import mytest这样引用,用法就和用其他python的模块一样了。


swig

首先要说明的是swig可以进行很多语言的调用转换,不止是可以让python调用c。swig和sip都被称作wrapper,就是说他对你的原 有函数进行了包装。看到之前用python c api的方式里,我们必须严格按照python c api的方式来写代码,破坏了原有c程序的可读性,于是wrapper的思想就是把原生c程序包装成python c api那种方式的代码,再去生成so文件。因此我们要做的是首先写c文件。

  1. int add(int a, int b){

  2.     return a+b;

  3. }

  4. int sub(int a, int b){

  5.     return a-b;

  6. }

然后再去写一个swig格式的接口文件。

  1. %module mytest

  2. %{

  3. extern int add(int a, int b);

  4. extern int sub(int a, int b);

  5. %}

  6.  

  7. extern int add(int a, int b);

  8. extern int sub(int a, int b);

然后就可以运行swig,他会自动生成python c api写的代码,并且会自动编译出so文件来调用。


sip

来看sip,sip是swig发展而来是方便python调用c的,所以基本使用方式都是差不多,只不过接口文件略有差异。

  1. %Module(name=mytest, language="C")

  2. int add(int a, int b);

  3. int sub(int a, int b);


ctypes

ctypes提供了另外的思路来调用c程序。首先ctypes是python的标准库,所以如果用ctypes你不需要额外的其他的东西。 ctypes让你可以在python直接写代码加载c的链接库so文件来调用,就是说如果你用so文件而没有源文件的话,你仍然可以用ctypes去调 用。

  1. from ctypes import *

  2.  

  3. f = 'mytest.so'

  4. cdll.LoadLibrary(f)

  5. api = CDLL(f)

  6. api.add.argtypes = [c_int, c_int]

  7. api.add.restype = c_int

  8. api.sub.argtypes = [c_int, c_int]

  9. api.sub.restype = c_int

  10.  

  11. print api.add(3, 2)

  12. print api.sub(3, 2)

有点像在python中去写接口文件,由于是python的标准库,所以这种方式用的还是蛮多的。


cython

cython的方法呢是利用类似python的语法来写调用c程序的接口,并且可以同时方便的地用c函数和python函数。看代码理解。

  1. int sub(int a, int b){

  2.     return a-b;

  3. }

我们可以有一些c写成的代码。

  1. cdef extern from 'test.c':

  2.     int sub(int a, int b)

  3.  

  4. def add(int a, int b):

  5.     return a+b

  6.  

  7. def mysub(a, b):

  8.     return sub(a, b)

然后在cython中我们既可以引入c文件调用c文件中的函数,也可以去调用python中的函数,调用cython程序会把他变成纯正的c文件,然后编译成so文件就可以使用了。

from cffi import FFI
ffi = FFI()
ffi.cdef("""
int add(int a, int b);
int sub(int a, int b);
""")
lib = ffi.verify('#include "mytest.c"')
print lib.add(1,2)

最后是cffi,cffi类似于ctypes直接在python程序中调用c程序,但是比ctypes更方便不要求编译成so再调用,注意到上面的 所有方式都是需要去编译成so文件后再在python中调用,而cffi允许你直接调用c文件来使用里面的函数了,为什么这么神奇呢,其实是cffi在解 释过程中才帮你把c编译为so文件的。。。

然后基本就是这样了,最后给我的感觉就是:基本上原生的python c api的写法最麻烦了,但是一些需要高级用法的话还是这个更容易控制;方便一点的就是用wrapper;ctypes好处是,他是python的标准模块 并且不需要另外写其他的额外程序(接口程序之类的);cython好处就是可以方便的同时调用c函数和python函数,并且是类python语法,用起 来很方便;CFFI好处是调用c更加方便,不用编译 so。最后本文只是对各种用法简单的介绍,并没有深入的对各种用法的优缺点进行比较,因此如果想了解更多内容还是去看官方文档吧。。。


本文转载自:http://www.isnowfy.com/introduction-to-python-c-extension/

openthings
粉丝 320
博文 1129
码字总数 675031
作品 1
东城
架构师
私信 提问
加载中

评论(2)

openthings
openthings 博主

引用来自“ZZWZZ”的评论

这个好用吗?最近想入手这个方法,求交流57
Python就是C写的,还是比较简单的。对于大的工程,还是建议使用SIP来进行封装,更简单一些。
ZZWZZ
ZZWZZ
这个好用吗?最近想入手这个方法,求交流57
Python的C/C++扩展——Python的C语言接口

文章首发于我的技术博客:你可以在上面看到更多的Python教程和python爬虫 Python语言最初是用C语言实现的一种脚本语言,后来被称为CPython,是因为后来又有其它语言实现的Python,比如Pytho...

呆木木人儿
03/11
28
0
C/C++ 和 Python混合编程

链接:https://www.zhihu.com/question/23003213/answer/56121859 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 #include int main(int argc, char *...

sirius_0
2018/04/21
0
0
SylixOS Python扩展库开发

1 适用范围 本文档适用于希望使用基于SylixOS进行Python扩展库开发的用户。 2 SylixOS Python简介 Python是一门面向对象的解释型的脚本语言,Python具有丰富和强大的库。它常被昵称为胶水语言...

zhaotongch
2018/09/03
28
0
使用C++编写python扩展模块

简介 长话短说,这里说的扩展Python功能与直接用其它语言写一个动态链接库,然后让Python来调用有点不一样(虽然本质是一样的)。而是指使用Python本身提供的API,使用C++来对Python进行功能...

openthings
2015/01/21
2.3K
0
Python是什么?简单了解pythonp-入门

简单了解python Python语言特色 Python是一门解释性语言 解释性语言:在系统中运行时需要使用解释器(如:php、java) 编译性语言:在系统中运行不需要解释器,可以直接运行(如:C、C++) ...

1229747455418890
02/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

64.监控平台介绍 安装zabbix 忘记admin密码

19.1 Linux监控平台介绍 19.2 zabbix监控介绍 19.3/19.4/19.6 安装zabbix 19.5 忘记Admin密码如何做 19.1 Linux监控平台介绍: 常见开源监控软件 ~1.cacti、nagios、zabbix、smokeping、ope...

oschina130111
今天
13
0
当餐饮遇上大数据,嗯真香!

之前去开了一场会,主题是「餐饮领袖新零售峰会」。认真听完了餐饮前辈和新秀们的分享,觉得获益匪浅,把脑子里的核心纪要整理了一下,今天和大家做一个简单的分享,欢迎感兴趣的小伙伴一起交...

数澜科技
今天
7
0
DNS-over-HTTPS 的下一代是 DNS ON BLOCKCHAIN

本文作者:PETER LAI ,是 Diode 的区块链工程师。在进入软件开发领域之前,他主要是在做工商管理相关工作。Peter Lai 也是一位活跃的开源贡献者。目前,他正在与 Diode 团队一起开发基于区块...

红薯
今天
13
0
CC攻击带来的危害我们该如何防御?

随着网络的发展带给我们很多的便利,但是同时也带给我们一些网站安全问题,网络攻击就是常见的网站安全问题。其中作为站长最常见的就是CC攻击,CC攻击是网络攻击方式的一种,是一种比较常见的...

云漫网络Ruan
今天
12
0
实验分析性专业硕士提纲撰写要点

为什么您需要研究论文的提纲? 首先当您进行研究时,您需要聚集许多信息和想法,研究论文提纲可以较好地组织你的想法, 了解您研究资料的流畅度和程度。确保你写作时不会错过任何重要资料以此...

论文辅导员
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部