【Python笔记】如何用C语言实现Python第三方扩展包

Python支持C/C++实现的第3方扩展包,在性能要求高的场合,这种特性显得尤其重要。

本文以实例说明定制Python扩展包的基本步骤。

1. 扩展包源码实现

按照Python官网教程Extending Python with C or C++说明的步骤,扩展模块的源文件实现如下:

#include <Python.h>

// forward declaration
void initpyext(void);

// self-defined error obj
static PyObject * ExtError;

int main(int argc, char * argv[])
{
    // Pass argv[0] to the Python interpreter
    Py_SetProgramName(argv[0]);
    // Initialize the Python interpreter. Required.
    Py_Initialize();

    initpyext();

    Py_Exit(0);
    // not reached, warning will be printed when build the extension
}

static PyObject * py_ext_test_func(PyObject * self, PyObject * args)
{
    const char * command;
    int sts;

    if(!PyArg_ParseTuple(args, "s", &command)) {
        return NULL;
    }

    sts = system(command);
    if(sts < 0) {
        PyErr_SetString(ExtError, "System command failed");
        return NULL;
    }

    return PyLong_FromLong(sts);
}

static PyMethodDef PyextMethods[] = {
    {"ext_cmd", py_ext_test_func, METH_VARARGS, "Execute a shell command." },
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC initpyext(void)
{
    PyObject * m;
    m = Py_InitModule("pyext", PyextMethods);
    if(NULL == m) {
        return;
    }

    ExtError = PyErr_NewException("pyext.error", NULL, NULL);
    Py_INCREF(ExtError);
    PyModule_AddObject(m, "error", ExtError);
}

上面的代码展示的是一个典型的针对Python的c扩展源码布局:

1. 定义main函数,作为扩展模块的入口

2. main函数调用initpyext(),initpyext函数名必须是initname格式,其中name是扩展模块名(扩展模块名由Py_InitModule的参数指定)

3. initpyext函数中,调用Py_InitModule初始化扩展模块名及其支持的方法名,其中method list是由static数组PyextMethods定义的

4. PyextMethods数组中,注册扩展模块支持的methods的name及其对应的函数指针

5. 为每个在PyextMethods数组中注册的method定义并实现具体的行为

2. 扩展文件编译/链接

根据官网文档Building C and C++ Extensions with distutils,可以这样编译扩展并安装至python第三方package目录:

$> python setup.py build
running build
running build_ext
building 'pyext' extension
gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/slvher/tools/python-2.7.5/include/python2.7 -c pyext.c -o build/temp.linux-x86_64-2.7/pyext.o
pyext.c: In function `main':
pyext.c:28: warning: control reaches end of non-void function
gcc -pthread -shared build/temp.linux-x86_64-2.7/pyext.o -o build/lib.linux-x86_64-2.7/pyext.so

注意:这里直接用python调用setup.py是因为在PATH中设置了python的默认环境变量,如果当前系统默认的python解释器不是我们想要用来编译扩展的解释器时,需要用python的绝对路径调用。

3. 安装扩展包

$> python setup.py install
running install
running build
running build_ext
running install_lib
copying build/lib.linux-x86_64-2.7/pyext.so -> /home/slvher/tools/python-2.7.5/lib/python2.7/site-packages
running install_egg_info
Writing /home/slvher/tools/python-2.7.5/lib/python2.7/site-packages/TestPyExtPackage-1.0-py2.7.egg-info

4. 验证是否可用

安装成功后,进入python解释器,import扩展模块后,可以调用其方法名:

>>> import pyext
>>> pyext.ext_cmd("echo hello world")
hello world
0L
>>> 

【参考资料】

1. Extending Python with C or C++

2. Building C and C++ Extensions with distutils

====================== EOF ==================

时间: 2024-12-25 13:59:54

【Python笔记】如何用C语言实现Python第三方扩展包的相关文章

关于如何让在离线环境下安装Python的pip第三方扩展包

注意:以下方法如果安装失败,那么一定是前置的依赖包没有安装,找到依赖包,下载过来用下面的方法安装,直到所有的前置包都安装完成.  Python的pip包一般有如下几种格式 tar.gz zip whl   tar.gz包离线安装 解压 cd到setup.py目录下 在cmd或者powershell下运行python setup.py install  或者 直接cd到存放tar.gz文件的目录在cmd或者powershell下 运行pip install xxxxxx.tar.gz  Zip包离

R语言结合RColorBrewer颜色扩展包绘制横向直方图

首先载入颜色扩展包RColorBrewer,颜色包的具体使用方法可参见这篇文章http://book.2cto.com/201408/45552.html library(RColorBrewer) 本文以hadoop集群wordcount程序的输出结果为数据源 数据的整理代码如下 x=read.delim("C:/Users/a/Desktop/sample.txt",header=FALSE) #读入文本数据 names(x)=c("word","co

Python之扩展包安装(scikit learn)

scikit learn 是Python下开源的机器学习包.(安装环境:win7.0 32bit和Python2.7) Python安装第三方扩展包较为方便的方法:easy_install + packages name 在官网 https://pypi.python.org/pypi/setuptools/#windows-simplified 下载名字为 的文件. 在命令行窗口运行 ,安装后,可在python2.7文件夹下生成Scripts文件夹.把路径D:\Python27\Scripts

High Performance Python 笔记(Python是门不错的语言,全栈程序员就用它好了!)

High Performance Python 目录 1Understanding Performant Python 2Profiling 3Lists and Tuples 4Dictionaries and Sets 5Iterators and Generators 6Matrix and Vector Computation 7Compiling to C 8Concurrency 9multiprocessing 10Clusters and Job Queues 11Using L

Python笔记之不可不知

Python软件已经安装成功有很长一段时间了,也即或多或少的了解Python似乎也很长时间了,也是偏于各种借口,才在现在开始写点总结.起初接触Python是因为公司项目中需要利用Python来测试开发的接口,于是开始了解这门解释性,面向对象,带有动态语义的高级语言,或是脚本语言,或是胶水语言.便在网上找了一个现成的Python爬虫,在本地测试运行成功,将新浪上面的所有博客地址扒取下来.真心想从基础学起,自己写个,于是,有了这份基础总结,项目模块的开发将在下一篇博文中贴出.敬请关注! 本博文仅记录

Python笔记(四)

在<Python笔记(三)>中,我记录关于Python中序列问题的知识.个人觉得确实比Java中的集合框架简单.之前也说了,Python是一种高级面向对象的语言,它的每一个变量都称为对象.今天我接触了面向对象的编程.下面是这篇博客的目录: 1.类与对象 2.输入输出 3.异常 类与对象: 我们都知道面向对象的语言具备四个特性:抽象,继承,封装,多态.Java,C++是这样,Python也不例外.在Python中,我们定义一个类,使用关键字class.形式如下:class classname:.

玩蛇(Python)笔记之基础Part2

玩蛇(Python)笔记之基础Part2 一.列表 1.列表 别的语言叫数组 python牛逼非要取个不一样的名字 1 age = 23 2 name = ["biubiubiu", "jiujiujiu", 22, age] 3 # namecopy = name 4 # namecopy.pop() 5 print(name) 6 # print(namecopy) List 2.列表取值 正常index 从零开始,,取倒数加负号 倒数第一就是[-1] 3.列表

Python笔记:替代case语句的字典和匿名函数(lambda)

在linux的shell中我们习惯使用case语句来做分支处理,然而Python中却省略了这个函数,经过多方查找,发现其实case语句在C语言中是通过查对应的hash表,来进行跳转的.在Python中我们可以通过三种方法来实现这种功能.1.字典:2.lambda:3.switch类. 1.字典 dictCase={'case1':func1,'case2':func2....'caseN':funcN} #注意字典中对应的是函数名,不要圆括号. 在调用的时候使用字典的get函数来实现defaul

嵩天老师的零基础Python笔记:https://www.bilibili.com/video/av15123607/?from=search&amp;seid=10211084839195730432#page=25 中的38-41讲

# -*- coding: utf-8 -*-#嵩天老师的零基础Python笔记:https://www.bilibili.com/video/av15123607/?from=search&seid=10211084839195730432#page=25 中的38-41讲# 文件# 文件是存储在外部介质上的数据或信息的集合# 文件是有序的数据序列# 常用的编码# ASCII码是标准化字符集# 7个二进制位编码# 表示128个字符 # ord() 将字符转化为ASCII码, chr() 将AS