Extending Python with C (Python 调用 C) - A Simple Example - Python list

原文阅读于极客学院 http://www.jikexueyuan.com/

Python/C API 使用简单,可以在 C 代码中操作你的 Python 对象。

需要以特定的方式编写 C 代码以供 Python 去调用。所有的 Python 对象都被表示为一种叫做 PyObject 的结构体,并且 Python.h 头文件中提供了各种操作它的函数。如果 PyObject 表示为 PyListType (列表类型) 时,可以使用 PyList_Size() 函数来获取该结构的长度,类似 Python 中的 len(list) 函数。大部分对 Python 原生对象的基础函数和操作在 Python.h 头文件中都能找到。

Python 调用 C 扩展的代码

# Though it looks like an ordinary python import, the addList module is implemented in C
import addListl = [1,2,3,4,5]
print "Sum of List - " + str(l) + " = " + str(addList.add(l))
though [ðəʊ]:conj. 即使,虽然,尽管, 纵然 adv. 不过,然而,可是,但是,话虽这样说 prep. 但
ordinary [ˈɔ:dnri]:  adj. 普通的,一般的,平常的,平庸的

导入并使用了一个叫做 addList 的 Python 模块。唯一差别就是这个模块并不是用 Python 编写的,而是 C。

addList.c

/*============================================================================Name        : addList.cAuthor      : Foreverstrong ChengVersion     : Feb 16, 2019Copyright   : Copyright 2019 DeepNorth LicenseDescription : Extending Python with C or C++, Ansi-style============================================================================*/// Python.h has all the required function definitions to manipulate the Python objects.
#include <Python.h>// This is the function that is called from your Python code.
static PyObject *addList_add(PyObject *self, PyObject *args)
{PyObject *listObj;// The input arguments come as a tuple, we parse the args to get the various variables.// In this case it's only one list variable, which will now be referenced by listObj.if (!PyArg_ParseTuple(args, "O", &listObj)){return NULL;}// Length of the list.long length = PyList_Size(listObj);// Iterate over all the elements.int i, sum = 0;for (i = 0; i < length; i++){// Get an element out of the list - the element is also a Python objects.PyObject *temp = PyList_GetItem(listObj, i);// We know that object represents an integer - so convert it into C long.long elem = PyInt_AsLong(temp);sum += elem;}// Value returned back to Python code - another Python object.// Build value here converts the C long to a Python integer.return Py_BuildValue("i", sum);
}/*============================================================================This is the docstring that corresponds to our 'add' function.============================================================================*/
static char addList_docs[] = "add( ): add all elements of the list.\n";/*============================================================================This table contains the relavent info mapping -<function-name in python module>, <actual-function>,<type-of-args the function expects>, <docstring associated with the function>.============================================================================*/
static PyMethodDef AddList_Methods[] =
{{"add", addList_add, METH_VARARGS, addList_docs},{NULL, NULL, 0, NULL}
};/*============================================================================addList is the module name, and this is the initialization block of the module.============================================================================*/
PyMODINIT_FUNC initaddList(void)
{(void) Py_InitModule("addList", AddList_Methods);
}

compile_addList.sh

#!/bin/bashecho "Extending Python with C or C++"gcc -fPIC -shared addList.c -o addList.so -I/usr/include/python2.7/ -lpython2.7

编写完成 C 模块,将下列代码保存为 setup.py.

# build the modulesfrom distutils.core import setup, Extensionsetup(name='addList', version='1.0',  \ext_modules=[Extension('addList', ['adder.c'])])

运行 setup.py,将我们的 C 文件编译安装到我们的 Python 模块中。

python setup.py install

Python.h 头文件中包含了所有需要的类型 (Python 对象类型的表示) 和函数定义 (对 Python 对象的操作)。
编写将要在 Python 调用的函数, 函数传统的命名方式由 {模块名}_{函数名} 组成,将其命名为 addList_add。然后在模块内实现函数的相关信息表,每行一个函数,以 {NULL, NULL, 0, NULL} 作为结束。模块初始化为 PyMODINIT_FUNC init{模块名}。

函数 addList_add 接受的参数类型为 PyObject 类型结构 (同时也表示为元组类型,因为 Python 中皆为对象,所以我们先用 PyObject 来定义)。传入的参数则通过 PyArg_ParseTuple() 来解析。第一个参数是被解析的参数变量。第二个参数是一个字符串,告诉我们如何去解析元组中每一个元素。字符串的第 n 个字母正是代表着元组中第 n 个参数的类型。例如,"i" 代表整形,"s" 代表字符串类型, "O" 则代表一个 Python 对象。接下来的参数是通过 PyArg_ParseTuple() 函数解析并保存元素。这样参数的数量和模块中函数期待得到的参数数量保持一致,并保证了位置的完整性。

例如传入一个字符串,一个整数和一个 Python 列表,可以这样去写:

int n;
char *s;
PyObject* list;
PyArg_ParseTuple(args, "siO", &n, &s, &list);

在这种情况下,我们只需要提取一个列表对象,并将它存储在 listObj 变量中。用列表对象中的 PyList_Size() 函数来获取它的长度,就像 Python 中调用 len(list)。

通过循环列表,使用 PyList_GetItem(list, index) 函数来获取每个元素,返回一个 PyObject * 对象。Python 对象也能表示 PyIntType,只要使用 PyInt_AsLong(PyObj *) 函数便可获得我们所需要的值。我们对每个元素都这样处理,最后得到它们的总和。

总和将被转化为一个 Python 对象并通过 Py_BuildValue() 返回给 Python 代码,这里的 "i" 表示我们要返回一个 Python 整形对象。

验证模块

# module that talks to the C code
import addListl = [1,2,3,4,5]
print "Sum of List - " + str(l) + " = " + str(addList.add(l))

输出结果:

Sum of List - [1, 2, 3, 4, 5] = 15

Python 调用 C 代码的另一种方式是使用 Cython,让 Python 编译的更快。Cython 和传统的 Python 比起来可以理解为另一种语言。

Extending Python with C (Python 调用 C) - A Simple Example - Python list相关推荐

  1. python延时执行函数_一日一技:在 Python 中实现延迟调用

    一日一技:在 Python 中实现延迟调用 收录于话题 #你不知道的 Python 71个 摄影:产品经理 产品经理的生日餐 熟悉 Golang 的同学都知道,Golang 里面有一个关键词叫做def ...

  2. Extending Python with C (Python 调用 C) - A Simple Example

    Extending Python with C (Python 调用 C) - A Simple Example great_module.c /*========================== ...

  3. Python可以调用Gpu吗_加快Python算法的四个方法:Numba篇

    CDA数据分析师 出品 相信大家在做一些算法经常会被庞大的数据量所造成的超多计算量需要的时间而折磨的痛苦不已,接下来我们围绕四个方法来帮助大家加快一下Python的计算时间,减少大家在算法上的等待时间 ...

  4. Python:使用ctypes库调用外部DLL 数据类型对应

    Python:使用ctypes库调用外部DLL(转) 前言

  5. [Python陷阱]os.system调用shell脚本获取返回值

    当前有shell个脚本/tmp/test.sh,内容如下: #!/bin/bash exit 11 使用Python的os.system调用,获取返回值是: >>> ret=os.s ...

  6. python+opencv用电脑调用手机摄像头或其他网路摄像头

    python+opencv用电脑调用手机摄像头或其他网路摄像头 文章目录: 1 获取手机摄像头或网络摄像头的ip 1.1 获取手机摄像头的ip 1.2 获取网络摄像头的IP 1.3 关于RTSP协议 ...

  7. Python 在子类中调用父类方法详解(单继承、多层继承、多重继承)

    Python 在子类中调用父类方法详解(单继承.多层继承.多重继承)   by:授客 QQ:1033553122   测试环境: win7 64位 Python版本:Python 3.3.5 代码实践 ...

  8. python py生成及调用pyc文件

    本文仅供学习交流使用,如侵立删!demo下载见文末 python py文件中调用pyc文件 1.生成pyc文件 # 目录下所有py文件生成pyc import compileall compileal ...

  9. Python 内部:可调用对象是如何工作的

    [这篇文章所描述的 Python 版本是 3.x,更确切地说,是 CPython 3.3 alpha.] 在 Python 中,可调用对象 (callable) 的概念是十分基本的.当我们说什么东西是 ...

最新文章

  1. Android Studio-设置鼠标悬停显示方法声明
  2. 模拟post请求--测试api是否可用--再交给ios开发
  3. SQL Server DBA常见面试 笔试问题
  4. atitit.微信项目开发效率慢的一些总结
  5. 在ubuntu 16.04上安装tensorflow,并测试成功
  6. 用c语言编译二叉树,C语言 数据结构平衡二叉树实例详解
  7. springmvc的主要功能_Spring MVC入门
  8. vSphere 5.0热添加
  9. newifimini出厂固件_新路由mini固件|newifi新路由mini OS固件V3.2.1.1100 抢先版 - 极光下载站...
  10. Linux学习之十一、环境变量的功能
  11. canpro脚本_周立功CANPro软件下载
  12. 安装前端插件 FeHelper
  13. 计算机机房不允许开窗么,机房新风系统的设计要求及规范 你了解多少?
  14. 爬虫:财政部PPP项目库
  15. 《互联网营销的流量池思维》——听课有感
  16. 家用无线路由器服务器,ZOL实测:家用无线路由器WiFi性能排行榜
  17. 用于地址解析的协议是服务器,用于解析域名的协议是什么?
  18. E1000 与 VMXNET3的 区别
  19. c语言开发exporter,cadvisor node-exporter引发的容器文件系统泄漏
  20. 消费商时代来临,日常消费成为投资

热门文章

  1. PO,BO,VO,DTO和POJO的概念区分
  2. 图片多选上传拖拽切换位置
  3. RCTF-2018 babyheap详解
  4. 2012第17周移动游戏榜单变化
  5. 备忘录可以统计字数吗?备忘录怎么查看字数
  6. JVM规范阅读:徒手解析class文件
  7. mosquitto --用户配置 及权限管理
  8. 8259的IRR、ISR、IMR的功能
  9. htc e8 android5.0官方下载,HTC更新Android 5.0/L名单公布 最低支持初代One M7
  10. Django Q对象