python扩展实现方法--python与c混和编程 转自:http://www.cnblogs.com/btchenguang/archive/2012/09/04/2670849.html
前言(更新:更方便易用的方式在http://www.swig.org/tutorial.html)
需要扩展Python语言的理由:
创建Python扩展的步骤
1. 创建应用程序代码
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 10
int fac(int n) {
if (n < 2)
return 1;
return n * fac(n - 1);
}
char *reverse(char *s) {
register char t;
char *p = s;
char *q = (s + (strlen(s) - 1));
while (p < q) {
t = *p;
*p++ = *q;
*q-- = t;
}
return s;
}
int main() {
char s[BUFSIZE];
printf("4! == %d\n", fac(4));
printf("8! == %d\n", fac(8));
printf("12! == %d\n", fac(12));
strcpy(s, "abcdef");
printf("reversing 'abcdef', we get '%s'\n", reverse(s));
strcpy(s, "madam");
printf("reversing 'madam', we get '%s'\n", reverse(s));
return 0;
}

2. 利用样板来包装代码
a. 包含python的头文件
b. 为每个模块的每一个函数增加一个型如PyObject* Module_func()的包装函数
int res;//计算结果值
int num;//参数
PyObject* retval;//返回值
//i表示需要传递进来的参数类型为整型,如果是,就赋值给num,如果不是,返回NULL;
res = PyArg_ParseTuple(args, "i", &num);
if (!res) {
//包装函数返回NULL,就会在Python调用中产生一个TypeError的异常
return NULL;
}
res = fac(num);
//需要把c中计算的结果转成python对象,i代表整数对象类型。
retval = (PyObject *)Py_BuildValue("i", res);
return retval;
}
int m;
if (!(PyArg_ParseTuple(args, "i", &num))) {
return NULL;
}
return (PyObject *)Py_BuildValue("i", fac(num));
}


Extest_reverse(PyObject *self, PyObject *args) {
char *orignal;
if (!(PyArg_ParseTuple(args, "s", &orignal))) {
return NULL;
}
return (PyObject *)Py_BuildValue("s", reverse(orignal));
}
Extest_doppel(PyObject *self, PyObject *args) {
char *orignal;
if (!(PyArg_ParseTuple(args, "s", &orignal))) {
return NULL;
}
//ss,就可以返回两个字符串,应该reverse是在原字符串上进行操作,所以需要先strdup复制一下
return (PyObject *)Py_BuildValue("ss", orignal, reverse(strdup(orignal)));
}
Extest_doppel(PyObject *self, PyObject *args) {
char *orignal;
char *reversed;
PyObject * retval;
if (!(PyArg_ParseTuple(args, "s", &orignal))) {
return NULL;
}
retval = (PyObject *)Py_BuildValue("ss", orignal, reversed=reverse(strdup(orignal)));
free(reversed);
return retval;
}
c. 为每个模块增加一个型如PyMethodDef ModuleMethods[]的数组
ExtestMethods[] = {
{"fac", Extest_fac, METH_VARARGS},
{"doppel", Extest_doppel, METH_VARARGS},
{"reverse", Extest_reverse, METH_VARARGS},
{NULL, NULL},
};
d. 增加模块初始化函数void initMethod()
Py_InitModule("Extest", ExtestMethods);
}
#include <stdlib.h>
#include <string.h>
#include "Python.h"
#define BUFSIZE 10
int fac(int n) {
if (n < 2)
return 1;
return n * fac(n - 1);
}
char *reverse(char *s) {
register char t;
char *p = s;
char *q = (s + (strlen(s) - 1));
while (p < q) {
t = *p;
*p++ = *q;
*q-- = t;
}
return s;
}
static PyObject *
Extest_fac(PyObject *self, PyObject *args) {
int res;
int num;
PyObject* retval;
res = PyArg_ParseTuple(args, "i", &num);
if (!res) {
return NULL;
}
res = fac(num);
retval = (PyObject *)Py_BuildValue("i", res);
return retval;
}
static PyObject *
Extest_reverse(PyObject *self, PyObject *args) {
char *orignal;
if (!(PyArg_ParseTuple(args, "s", &orignal))) {
return NULL;
}
return (PyObject *)Py_BuildValue("s", reverse(orignal));
}
static PyObject *
Extest_doppel(PyObject *self, PyObject *args) {
char *orignal;
char *resv;
PyObject *retval;
if (!(PyArg_ParseTuple(args, "s", &orignal))) {
return NULL;
}
retval = (PyObject *)Py_BuildValue("ss", orignal, resv=reverse(strdup(orignal)));
free(resv);
return retval;
}
static PyMethodDef
ExtestMethods[] = {
{"fac", Extest_fac, METH_VARARGS},
{"doppel", Extest_doppel, METH_VARARGS},
{"reverse", Extest_reverse, METH_VARARGS},
{NULL, NULL},
};
void initExtest() {
Py_InitModule("Extest", ExtestMethods);
}
int main() {
char s[BUFSIZE];
printf("4! == %d\n", fac(4));
printf("8! == %d\n", fac(8));
printf("12! == %d\n", fac(12));
strcpy(s, "abcdef");
printf("reversing 'abcdef', we get '%s'\n", reverse(s));
strcpy(s, "madam");
printf("reversing 'madam', we get '%s'\n", reverse(s));
test();
return 0;
}
3. 编译与测试
a. 创建setup.py
from distutils.core import setup, Extension
MOD = 'Extest'
setup(name=MOD, ext_modules=[Extension(MOD, sources=['Extest.c'])])
b. 通过运行setup.py来编译和连接你的代码




c. 进行调试
from ctypes import *
import os
#需要使用绝对路径
extest = cdll.LoadLibrary(os.getcwd() + '/Extest.so')
print extest.fac(4)


Extest_test(PyObject *self, PyObject *args) {
test();
#返回空的话,就使用下面这一句
return (PyObject *)Py_BuildValue("");
}
简单性能比较
import time
start = time.time()
a = Extest.reverse("abcd")
timeC = time.time() - start
print 'C costs', timeC, 'the result is', a
start = time.time()
b = list("abcd")
b.reverse()
b = ''.join(b)
timePython = time.time()-start
print 'Python costs', timePython, 'the result is', b

python扩展实现方法--python与c混和编程 转自:http://www.cnblogs.com/btchenguang/archive/2012/09/04/2670849.html的更多相关文章
- python扩展实现方法--python与c混和编程
前言 需要扩展Python语言的理由: 创建Python扩展的步骤 1. 创建应用程序代码 2. 利用样板来包装代码 a. 包含python的头文件 b. 为每个模块的每一个函数增加一个型如PyObj ...
- 自定义python扩展类型
目标:自定义一个C\C++矩阵类,有几个用于演示的矩阵运算函数或者操作,将其通过 PyTypeOject newType的方式注册到python中成为一种新的类型,并且要可继承. 预备知识 建议先运行 ...
- Python学习(25):Python执行环境
转自 http://www.cnblogs.com/BeginMan/p/3191856.html 一.python特定的执行环境 在当前脚本继续进行 创建和管理子进程 执行外部命令或程序 执行需要输 ...
- Python List extend()方法
Python List extend()方法 Python 列表 描述 extend() 函数用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表). 语法 extend()方法语法 ...
- [转]Python存取XML方法简介
转自:http://www.cnblogs.com/salomon/archive/2012/05/28/2518648.html 目前而言,Python 3.2存取XML有以下四种方法: 1.Exp ...
- python 存取xml方法
或者也可以参考http://www.cnblogs.com/xiaowuyi/archive/2012/10/17/2727912.html中内容 目前而言,Python 3.2存取XML有以下四种方 ...
- Python os.getcwd() 方法
Python os.getcwd() 方法 Python OS 文件/目录方法 概述 os.getcwd() 方法用于返回当前工作目录. 语法 getcwd()方法语法格式如下: os.getcwd ...
- Python序列的方法(转)
在快速教程中,我们了解了最基本的序列(sequence).回忆一下,序列包含有定值表(tuple)和表(list).此外,字符串(string)是一种特殊的定值表.表的元素可以更改,定值表一旦建立,其 ...
- python之路:python基础3
---恢复内容开始--- 本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 ...
随机推荐
- 关于datatable linq的转换
关于datatable datarow DataTable paraval = GetParaVal(DateCondition, strUrl, Page, RowPage, iYearMonthN ...
- 初识Hadoop一,配置及启动服务
一.Hadoop简介: Hadoop是由Apache基金会所开发的分布式系统基础架构,实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS:Hadoo ...
- 第5章 jQuery对表单、表格的操作及更多应用
本章主要是对前面4章的小结和应用. 一. 表单form应用 表单分为3个组成部分 (1)form标签 表单可包含文本域,复选框,单选按钮等等.表单用于向指定的 URL 传递用户数据. (2)表单域 - ...
- C#----Get和Set在属性中的使用
Get和Set在属性中的作用: 第一个作用:保证数据的安全性,对字段进行了有效的保护. 第二个作用:起到监视作用 private int width=0; public int Width { get ...
- 通过KUDU获取Azure网站的日志
部署到Azure上的website,由于无法通过RDP的方式去登录查看log,所以我们只能通过FTP的方式或者kudu的方式进行查看,具体如下: 1.使用FTP账户和密码登录网站的KUDU界面: 如您 ...
- input 获取当前id,name
<input name=" src="toright.png" value="mp3"> <script language=&quo ...
- ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)--MySQL错误
MySQL错误整理: 错误一: ERROR (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/my ...
- Semantic ui 学习笔记 持续更新
这个semantic 更新版本好快~ 首先是代码的标识<code></code> 具体样式就是红框这样的 圈起来代码感觉不错 不过要在semantic.css里在加上如下样式~ ...
- IIS 8.5 伪静态去掉index.php thinkphp 3.2.2
因为测试都是在win下开发的 win8.1企业版 II8.5 首先安装 Thinkphp 3.2.2 URL Rewrite Module 2.0 http://www.iis.net/downlo ...
- Lua弱引用table
弱引用table 与python等脚本语言类似地,Lua也采用了自动内存管理(Garbage Collection),一个程序只需创建对象,而无需删除对象.通过使用垃圾收集机制,Lua会自动删除过期对 ...