庄泽波の博客

好记性不如烂笔头

Python和C扩展实现方法

一、Python和C扩展

cPython是C编写的,python的扩展可以用C来写,也便于移植到C++.

编写的Python扩展,需要编译成一个.so的共享库。

Python程序中。

官方文档:https://docs.python.org/2/extending/extending.html#writing-extensions-in-c

 

二、举例

>>> import spam
>>> status = spam.system("ls -l")

 我们需要创建一个spam.c的文件模块,这个模块是C实现。开头必须有

  #include <Python.h>

 下面实现以上的举子:

static PyObject *
spam_system(PyObject *self, PyObject *args)
{
    const char *comment;
    int sts;

    if (!PyArg_ParseTuple(args, "s", &command))
        return NULL;
    sts = system(command);
    return Py_BuildValue("i", sts);
}


上述函数的Python扩展中C函数有两个参数:self, args,这两个是必须的。

 

三、模块方法和函数初始化

1、定义模块及帮助文档。模块叫system,指定执行函数spam_system, 帮助文档“Execute a shell command”

static PyMethodDef SpamMethods[] = { 
    {"system", spam_system, METH_VARARGS, "Execute a shell command."},
    {NULL, NULL, 0, NULL}
};

在编译完之后,导入模块,执行如下help命令,就会出现文档

In [5]: help(spam)


Help on module spam:

NAME
    spam

FILE
    /usr/lib/python2.6/site-packages/spam.so

FUNCTIONS
    system(...)
        Execute a shell command.

 

2、初始spam,初始化模块函数一定要init[module],保持一致

void initspam() {
    Py_InitModule("spam", SpamMethods);
}

 

三、编译

1、编译模块时,需要编写setup.py文件

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from distutils.core import setup, Extension

MOD = "spam"
setup(name=MOD, ext_modules=[Extension(MOD, sources=['spam.c'])])

模块名name和扩展模块。

2、进行编译

[root@local PycExt]# python setup.py build
running build
running build_ext
building 'spam' extension
gcc -pthread -fno-strict-aliasing -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -D_GNU_SOURCE -fPIC -fwrapv -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/usr/include/python2.6 -c spam.c -o build/temp.linux-i686-2.6/spam.o
In file included from /usr/include/python2.6/pyconfig.h:4,
                 from /usr/include/python2.6/Python.h:8,
                 from spam.c:3:
/usr/include/python2.6/pyconfig-32.h:1034:1: warning: "_POSIX_C_SOURCE" redefined
In file included from /usr/include/stdio.h:28,
                 from spam.c:1:
/usr/include/features.h:162:1: warning: this is the location of the previous definition
In file included from /usr/include/python2.6/pyconfig.h:4,
                 from /usr/include/python2.6/Python.h:8,
                 from spam.c:3:
/usr/include/python2.6/pyconfig-32.h:1043:1: warning: "_XOPEN_SOURCE" redefined
In file included from /usr/include/stdio.h:28,
                 from spam.c:1:
/usr/include/features.h:164:1: warning: this is the location of the previous definition
gcc -pthread -shared build/temp.linux-i686-2.6/spam.o -L/usr/lib -lpython2.6 -o build/lib.linux-i686-2.6/spam.so

 

生成一个build的文件夹,里面有spam.so库

[root@local PycExt]# ls
build  setup.py  spam.c

 

3、安装

[root@local PycExt]# python setup.py install
running install
running build
running build_ext
running install_lib
copying build/lib.linux-i686-2.6/spam.so -> /usr/lib/python2.6/site-packages
running install_egg_info
Removing /usr/lib/python2.6/site-packages/spam-0.0.0-py2.6.egg-info
Writing /usr/lib/python2.6/site-packages/spam-0.0.0-py2.6.egg-info

执行命令如上,就安装好了。

 

四、使用模块

In [1]: import spam

In [2]: spam.system("ls -la")
total 20
drwxr-xr-x.  3 root root 4096 Apr  8 22:07 .
drwxr-xr-x. 10 root root 4096 Apr  8 21:01 ..
drwxr-xr-x.  4 root root 4096 Apr  8 21:51 build
-rw-r--r--.  1 root root  171 Apr  8 21:48 setup.py
-rw-r--r--.  1 root root  549 Apr  8 22:07 spam.c
Out[2]: 0

In [3]: 

如上,即为python扩展相关内容...

 

spam.c

#include <stdio.h>
#include <stdlib.h>
#include "Python.h"


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

    if (!PyArg_ParseTuple(args, "s", &command))
        return NULL;
    sts = system(command);
    return Py_BuildValue("i", sts);
}

static PyMethodDef SpamMethods[] = {
    {"system", spam_system, METH_VARARGS, "Execute a shell command."},
    {NULL, NULL, 0, NULL}
};

void initspam() {
    Py_InitModule("spam", SpamMethods);
}

int main(int argc, char *argv[])
{
    return 0;
}

setup.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from distutils.core import setup, Extension

MOD = "spam"
setup(name=MOD, ext_modules=[Extension(MOD, sources=['spam.c'])])

 

posted on 2015-04-08 21:08  庄泽波  阅读(847)  评论(0编辑  收藏  举报

导航