当python的基本功能无法满足要求。或者是为了保密源码(.py)、遇到性能瓶颈时,我们经常要扩展python,扩展语言能够是C/C++、Java、C#等。

为python创建扩展须要三个基本的步骤:创建应用程序代码;利用样板来包装代码;编译与測试。

1、 创建应用程序代码

我们创建一个C代码PythonEx.c,实现两个函数fac()和reverse(),分别用来求阶乘和逆转字符串,test()函数是用来測试fac()和reverse()基本功能的。以防问题带入python。

// PythonEx.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h> int fac(int n)
{
if (n < 2) {
return (1);
}
else {
return (n) * fac(n - 1);
}
} char* reverse(char *s)
{
register char t;
register char *p = s;
register char *q = (s + strlen(s) -1); while (p < q) {
t = *p;
*p++ = *q;
*q-- = t;
} return s;
} int test()
{
char s[BUFSIZ]; printf("3! = %d\n", fac(3));
printf("6! = %d\n", fac(6));
printf("9! = %d\n", fac(9)); strcpy(s, "abcdefg");
printf("'abcdefg' after reversing is '%s'\n", reverse(s));
strcpy(s, "python");
printf("'python' after reversing is '%s'\n", reverse(s)); return 0;
}

2、 用样板包装代码

样板是扩展代码与python解释器之间进行交互的桥梁,主要分为以下4步。

a.包括python的头文件。

找到python头文件位置并确保编译器的訪问权限,然后在代码中inlcude这个头文件,例如以下:

#include “Python.h”

b.为每个模块的每个函数添加一个型如PyObject* Module_func()的包装函数。

这部分须要为全部想被python环境訪问的函数都添加一个静态的函数。函数的返回值类型为PyObject*,函数名前面要加上模块名和一个下划线。

包装函数的用处就是先把python的值传递给C,然后调用我们想要调用的相关函数。当这个函数完毕要返回python的时候,把函数的计算结果转换成python的对象,然后返回给python。那么。在从python到C的转换就用PyArg_Parse*系列函数,在从C转到python的时候,就用Py_BuildValue()函数。

以下我们包装fac()和reverse()函数,如果其模块名为CustomPy,例如以下:

static PyObject* CustomPy_fac(PyObject *self, PyObject *args)
{
int num;
if (!PyArg_ParseTuple(args, "i", &num)) { // i i.e. int->int
return NULL;
}
return (PyObject*)Py_BuildValue("i", fac(num)); // i i.e. int->int
} static PyObject* CustomPy_reverse(PyObject *self, PyObject *args)
{
char *orig_str; // original
char *dup_str; // reversed
PyObject *retval;
if (!PyArg_ParseTuple(args, "s", &orig_str)) { // s i.e. str->char*
return NULL;
}
retval = (PyObject*)Py_BuildValue(
"ss", // s i.e. char*->str
orig_str,
dup_str = reverse(strdup(orig_str))); // strdup
free(dup_str); // free after strdup
return retval; // return tuple(orig_str, dup_str)
} static PyObject* CustomPy_test(PyObject *self, PyObject *args)
{
test();
return (PyObject*)Py_BuildValue("");
}

以下是Python和C/C++之间的数据格式——

FormatCode PythonType C/C++Type

s str char*

z str/None char*/NULL

i int int

l long long

c str char

d float double

D complex Py_Complex*

o (any) PyObject*

S str PyStringObject

c.为每个模块添加一个型如PyMethodDef ModuleMethods[]的数组。

static PyMethodDef CustomPyMethods[] = {
{"fac", CustomPy_fac, METH_VARARGS},
{"reverse", CustomPy_reverse, METH_VARARGS},
{"test", CustomPy_test, METH_VARARGS},
{NULL, NULL},
};

完毕包装函数后。把他们添加到一个数组中,以便于python解释器能够导入并调用它们。

每个数组都包括了函数在python中的名字、对应的包装函数的名字以及一个METH_VARARGS常量,这个常量表示參数以tuple形式传入。最后是一个NULL数组表示列表结束。

d.添加模块初始化函数void initModule()

void initCustomPy()
{
Py_InitModule("CustomPy", CustomPyMethods);
}

这部分代码在模块被导入的时候被解释器调用。

另外。创建扩展还能够先写包装代码,使用桩函数、測试函数或哑函数,在开发过程中慢慢地把这些函数用有实际功能的函数替换。

3、编译与測试

为了让新python扩展能被创建。须要把它们与python库放在一起编译,曾经可能要用到Makefile,如今使用distutils模块就能够了,能够方便地编译、安装和分发这些模块、扩展和包。仅仅需创建一个setup.py脚本即可。

#!/usr/bin/env python 

from distutils.core import setup, Extension 

MOD = 'CustomPy'
setup(name = MOD, ext_modules = [Extension(MOD, sources = [PythonEx.c])])

以下直接执行setup.py脚本来创建自己定义模块。或者是install到python环境里,终于会生成一个so文件,接着import这个模块就能够使用了。

还有两点须要注意的是,python的垃圾自己主动回收策略是引用计数。以及线程安全操作,这些都能够添加到自己定义的模块中。

上面的样例中用C扩展了Python,我们还能够用Java扩展Jython,使用C#或者VB .NET扩展IronPython。如果在win32下,python还能够使用其COM(市场名字为ActiveX)操作Microsoft Office。

【Python】python扩展的更多相关文章

  1. Python 7 —— 扩展与嵌入

    Python 7 —— 扩展与嵌入 所谓扩展是指,在Python当中调用其他语言,由于Python的问题主要是效率,这里的扩展主要是指扩展C C++程序(重点) 所谓嵌入是指,在其他语言当中可以调用P ...

  2. windows 下 使用codeblocks 实现C语言对python的扩展

    本人比较懒就粘一下别人的配置方案了 从这开始到代码 摘自http://blog.csdn.net/yueguanghaidao/article/details/11538433 一直对Python扩展 ...

  3. Python之美[从菜鸟到高手]--一步一步动手给Python写扩展(异常处理和引用计数)

    我们将继续一步一步动手给Python写扩展,通过上一篇我们学习了如何写扩展,本篇将介绍一些高级话题,如异常,引用计数问题等.强烈建议先看上一篇,Python之美[从菜鸟到高手]--一步一步动手给Pyt ...

  4. Python C++扩展

    Python C++扩展 前段时间看了一篇文章,http://blog.jobbole.com/78859/, 颇有感触,于是就结合自己工作中的知识作了一个简单的Python移动侦测:移动侦测的算法使 ...

  5. Python3.x:python: extend (扩展) 与 append (追加) 的区别

    Python3.x:python: extend (扩展) 与 append (追加) 的区别 1,区别: append() 方法向列表的尾部添加一个新的元素.只接受一个参数: extend()方法只 ...

  6. python基础扩展(二)

    python基础扩展(二) 常用操作 1.startswith(以什么开始) endswith(y)什么结束 s='taiWanw39dd' print(s.startswith('t')) #意思是 ...

  7. Python的扩展接口[3] -> Matlab引擎 -> 使用 Python 调用 Matlab 程序

    Python - Matlab 目录 Python-Matlab 引擎 Python-Matlab 数组 Python-Matlab 基本操作 Python-Matlab 调用 m 文件 Matlab ...

  8. python --- Python中的callable 函数

    python --- Python中的callable 函数 转自: http://archive.cnblogs.com/a/1798319/ Python中的callable 函数 callabl ...

  9. Micro Python - Python for microcontrollers

    Micro Python - Python for microcontrollers MicroPython

  10. 从Scratch到Python——python turtle 一种比pygame更加简洁的实现

    从Scratch到Python--python turtle 一种比pygame更加简洁的实现 现在很多学校都开设了Scratch课程,学生可以利用Scratch创作丰富的作品,然而Scratch之后 ...

随机推荐

  1. Java常用工具类---image图片处理工具类、Json工具类

    package com.jarvis.base.util; import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStre ...

  2. ssh设置免秘钥登录

    系统:CentOS7.2 需求:A服务器的fab用户需要使用www用户免秘钥登录到B服务器 换句话说,就是在A服务器的fab用户下,ssh    www@B服务ip   -p  端口  ,然后登录过去 ...

  3. JavaSE-11 接口

    学习要点 接口的定义 接口作为约定 接口作为能力 接口 为什么使用接口 需求描述 要求实现防盗门的功能(防盗门:带锁的门). 需求分析 门有“开”和“关”的功能,锁有“上锁”和“开锁”的功能. 将门和 ...

  4. [Python3网络爬虫开发实战] 1.6.2-Tornado的安装

    Tornado是一个支持异步的Web框架,通过使用非阻塞I/O流,它可以支撑成千上万的开放连接,效率非常高,本节就来介绍一下它的安装方式. 1. 相关链接 GitHub:https://github. ...

  5. C语言标准库函数总结

    一.动态内存分配1.malloc  原型:extern void *malloc(unsigned int num_bytes);  用法:#include <alloc.h>  功能:分 ...

  6. Buffer.from(arrayBuffer[, byteOffset[, length]])

    Buffer.from(arrayBuffer[, byteOffset[, length]]) arrayBuffer - 一个 TypedArray 或 new ArrayBuffer() 的 . ...

  7. Python中的列表(2)

    一.从列表中删除元素 使用del 语句删除. books = ['Pride and Prejudice','Jane Eyre','The Catcher in the Rye'] print(bo ...

  8. 转载,Django组件

    知识预览 一 Django的form组件 二 Django的model form组件 三 Django的缓存机制 四 Django的信号 五 Django的序列化 回到顶部 一 Django的form ...

  9. Uva 816 Abbott的复仇(三元组BFS + 路径还原)

    题意: 有一个最多9*9个点的迷宫, 给定起点坐标(r0,c0)和终点坐标(rf,cf), 求出最短路径并输出. 分析: 因为多了朝向这个元素, 所以我们bfs的队列元素就是一个三元组(r,c,dir ...

  10. echarts的简单应用之(二)饼图

    接上一篇文章: echarts的简单应用之(一)柱形图:https://www.cnblogs.com/jylee/p/9359363.html 本篇文章讲述饼图,撇过折线图不说,是因为折线图与柱形图 ...