本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!!

python语言可以对c程序代码进行调用,以弥补python语言低性能的缺点。当然,它也不是直接就可以调用,需要我们对c代码进行一些中间过程处理,其基本流程如下:

1.创建c程序功能代码
------------1.1创建.c源程序文件(py_test1.c)
------------1.2创建.h头文件(py_test1.h)
2.python类型适配,包装c代码(写包裹文件)(py_test1wrapper.c)
------------2.1.包含Python.h头文件(在python安装目录下的include目录下找到)
------------2.2.为每一个函数设置一个PyObject *Module_func()的包裹函数
------------2.3.为模块增加一个PyMethodDef ModuleMethods[]的数组
------------2.4.增加模块的初始化函数void initModule()
3.编译和测试
-------------3.1编译安装到python环境
--------------------3.1.1)创建setup.py
--------------------3.1.2)运行setup.py编译和链接c的扩展代码
-------------3.2测试
--------------------3.2.1)从Python中导入模块
--------------------3.2.2)测试

  • 创建c程序功能代码
    一、创建.c源程序文件py_test1.c
    这是程序的具体功能代码,也就是python需要调用的c源程序。这里主要写了三个方法,最终我们就会实现python来调用这三个方法。

     #include<stdio.h>
    #include<stdlib.h>
    #include<string.h> //求阶乘
    int fac(int n) {
    if(n < 2)
    return 1; return n*fac(n-1);
    } //字符串逆序
    char *reverse(char *s) {
    //比如输入abcdefg,则返回gfedcba
    char t,*p = s ,*q = (s+strlen(s)-1); while(s && (p<q)) {
    t = *p;
    *p++ = *q;
    *q-- = t;
    } return s;
    } int test(void) //测试main方法,改成普通的test方法
    // int main(void)
    {
    char s[]; printf("5! = %d\n",fac(5)); //5的阶乘 printf("10! = %d\n",fac(10)); // 10的阶乘 strcpy(s,"hello world");
    printf("reversing 'hello world',we get '%s'\n",reverse(s)); return 0;
    }

    c源程序

    二、创建.h头文件py_test1.h
    接下来写一个就像stdio.h这样的头文件,方面后面引用。这个文件里面主要就是声明了py_test1.c中的三个方法。

     #ifndef PYTEST1_H_
    #define PYTEST1_H_ int fac (int n) ;
    char *reverse(char *s) ;
    int test(void) ; #endif
  • 写包裹文件py_test1wrapper.c
    这个包裹文件其实也是一段c语言代码,只是这一段代码比较特殊,它需要除c语言外还有一定的规则来创建它,这些规则就是python调用c定义的,必须遵循。
    1.必须include包含Python.h这个头文件,可以说这里就慢慢地去靠向python了。这个头文件在python安装目录下的include目录下找到它,但我们并不需要去知道它在哪儿。
    2.必须include包含py_test1.h这个头文件,这个就是上一步我们创建的那个头文件。
    3.还记得我们的py_test1.c这个源程序文件吗?现在我们需要对它里面的每个方法(这里是三个)都要设置一个包裹函数,它必须以PyObject为返回值,并且每个函数都有两个必须的参数。
    4.还要在这个文件里添加一个模块数组,类型必须是PyMethodDef,它用来定义方法名以及方法名与包裹函数的对应关系。
    5.最后还要添加一个模块的初始化函数void initModule(),这里的函数名必须以init和模块名组成。
    下面就是这个包裹文件的完整代码:
     #include "Python.h"
    #include <stdlib.h>
    #include <string.h>
    #include "py_test1.h"
    /** **包裹文件 **/ //为fac函数设置包裹函数(函数名、参数都有一定的规则,要注意)
    static PyObject *py_test1_fac(PyObject *self,PyObject *args)
    { int num ;
    //将python的数据类型int args通过i的方式转换成能被c识别的类型int num
    //i:表示将python的整型转成c的整型 ,其它类型可百度
    if (!PyArg_ParseTuple(args,"i",&num))
    return NULL; //调用c的对应函数并得到返回值,
    //然后将返回值c的数据类型int通过i的方式转换成能被python识别的类型int
    //最后强转成PyObject类型
    return (PyObject *)Py_BuildValue("i",fac(num)); } //为reverse函数设置包裹函数(由于python中有reverse函数,不能使用)
    static PyObject *py_test1_doppel(PyObject *self,PyObject *args)
    {
    char *src;
    char *mstr;
    PyObject *retval; //s:python中str ----->C中char *
    if (!PyArg_ParseTuple(args,"s",&src))
    return NULL; //申请存储空间
    mstr = malloc(strlen(src) +);
    //拷贝src到mstr
    strcpy(mstr,src);
    //调用reverse方法,逆序字符串
    reverse(mstr);
    //这里把原字符串和转换后的字符串返回
    retval = (PyObject *) Py_BuildValue("ss",src,mstr);
    //释放空间
    free(mstr); return retval;
    } //为test函数设置包裹函数
    static PyObject *py_test1_test(PyObject *self,PyObject *args)
    {
    //直接调用c函数
    test(); return (PyObject *)Py_BuildValue("");
    } //添加模块数组(注意是PyMethodDef,不要错写成PyMethondDef)
    //定义对应的方法名,后面Python调用的时候就用这里面的方法名调用
    static PyMethodDef py_test1Methods[] = {
    {"fac",py_test1_fac,METH_VARARGS},
    {"doppel",py_test1_doppel,METH_VARARGS},
    {"test",py_test1_test,METH_VARARGS},
    {NULL,NULL},
    }; //模块初始化函数
    void initpy_test1(void)
    {
    Py_InitModule("py_test1",py_test1Methods);
    }

    包裹文件

    到此为止,准备工作可以说已经完成了,接下来就需要编译、安装上面的那些文件了,怎么编译呢?

  • 编译、安装和测试
    一、编译安装
      1.创建setup.py文件,文件内容也很简单,主要功能就是使用python的自带模块,将包裹文件编译。
     #incoding:utf-8
    from distutils.core import setup,Extension
    #模块名
    MOD = 'py_test1'
    #资源(要编译和链接的代码文件)
    source = ['py_test1.c','py_test1wrapper.c'] #调用setup函数,编译和链接
    setup(name=MOD,ext_modules=[Extension(MOD,sources=source)])

      那如果运行这个setup.py 程序呢?这里就不能直接build了,需要到命令行里操作,定位要当前目录后通过命令python setup.py build来编译setup.py文件(出现各种错误,如:error: Unable to find vcvarsall.bat请看文章最后)
      

      2.编译完成过后,可以在当前文件目录下找到一个build文件夹,里面就是编译过后的内容了,我们也无需知道里面到底是些什么文件。编译完成我们怎么使用?别急,我们还要安装它们到python的库中,同样通过命令python setup.py install安装。
      

    这里其实就可以发现其实是往我们本地python库中安装了文件,也就是一个模块。在python安装目录下Lib目录的site-packages文件夹下。现在我们就可以使用它了。

    二、测试
      现在就可以使用python来调用最开始写的那个c程序了,别忘了要导入模块哦~
    测试程序test.py:

     #incoding:utf-8
    import py_test1
    print help(py_test1) #查看里面都要哪些方法
    py_test1.test() #调用test函数
    print "-"*50
    print py_test1.fac(9) #调用fac()求阶乘的函数
    print py_test1.doppel("yycsetup") #调用逆序函数

    运行输出:

     Help on module py_test1:
    
     NAME
    py_test1 FILE
    d:\python27\lib\site-packages\py_test1.pyd FUNCTIONS
    doppel(...) fac(...) test(...) None
    5! = 120
    10! = 3628800
    reversing 'hello world',we get 'dlrow olleh'
    --------------------------------------------------
    362880
    ('yycsetup', 'putescyy')
    [Finished in 0.5s]
  • 错误解决

    错误提示error: Unable to find vcvarsall.bat
    解决地址 : 其实这个错就是缺少文件vcvarsall.bat,基本解决思路就是安装VCForPython27(安装过后可能提示找不到vc),修改python源代码(修改方法返回值)。下面这几个地址值得参考,标红的为重要解决思路。
    ------------https://www.cnblogs.com/yyds/p/7065637.html
    ------------安装VCForPython27:https://www.microsoft.com/en-us/download/details.aspx?id=44266
    ------------升级setuptools:https://pypi.org/project/setuptools/
    ------------设置setuptools环境变量:https://www.cnblogs.com/fbwfbi/p/4509622.html
    ------------修改方法返回值:https://www.cnblogs.com/lazyboy/p/4017567.html

Python基础笔记系列十四:python无缝调用c程序的更多相关文章

  1. Python基础笔记系列十二:requests模块的简单应用

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! httpbin httpbin这个网站能测试 HTTP 请求和响应的各种信 ...

  2. Python基础笔记系列十:模块

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 模块 #1.类比于java中的jar包,模块能让你能够有逻辑地组织你的Py ...

  3. Python基础笔记系列十一:标准输入输出、文件读写和指针等操作

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 标准输入输出一.输入 在sublime中这个时候需要安装SublimeRE ...

  4. Python基础笔记系列一:基本工具与表达式

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 工具基础(Windows系统下)传送门:Python基础笔记系列四:工具的 ...

  5. Python学习笔记(十四)

    Python学习笔记(十四): Json and Pickle模块 shelve模块 1. Json and Pickle模块 之前我们学习过用eval内置方法可以将一个字符串转成python对象,不 ...

  6. python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法

    python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法window安装redis,下载Redis的压缩包https://git ...

  7. Python学习笔记(十四):模块高级

    以Mark Lutz著的<Python学习手册>为教程,每天花1个小时左右时间学习,争取两周完成. --- 写在前面的话 2013-7-23 21:30 学习笔记 1,包导入是把计算机上的 ...

  8. python学习笔记系列----(四)模块

    这一章主要是叙述了python模块的概念以及包的概念,还有它们的使用:收获也是大大的. 提起python文件,经常会听到3个名词,python脚本,python模块,python包.脚本的概念是从py ...

  9. Python 学习笔记(十)Python集合(二)

    集合常用的方法 add()       向集合中增加一个元素,如果集合中已经有了这个元素,那个这个方法就会失效 >>> help(set.add) Help on method_de ...

随机推荐

  1. matrix---简单dp,边界边界-_-

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5569 简单dp,恶心的边界处理,无语: if((i+j)%2==1) dp[i][j]=a[i-1][ ...

  2. python中读取json文件报错,TypeError:the Json object must be str, bytes or bytearray,not ‘TextIOWrapper’

    利用python中的json读取json文件时,因为错误使用了相应的方法导致报错:TypeError:the Json object must be str, bytes or bytearray,n ...

  3. PHP归档phar性能測试

    PHP自从5.3后新增PHAR归档,Phar 归档的概念来自 Java™ 技术的 JAR 归档,它同意使用单个文件打包应用程序.这个文件里包括运行应用程序所需的全部东西.该文件不同于单个可运行文件,后 ...

  4. 002-shell变量定义、使用、字符串、数组、注释

    一.变量定义 定义变量时,变量名不加美元符号($) name="lhx" 注意,变量名和等号之间不能有空格.同时,变量名的命名须遵循如下规则: 命名只能使用英文字母,数字和下划线, ...

  5. DIV+CSS如何让文字垂直居中?

    在说到这个问题的时候,也许有人会问CSS中不是有vertical-align属性来设置垂直居中的吗?即使是某些浏览器不支持我只需做少许的CSS Hack技术就可以啊!所以在这里我还要啰嗦两句,CSS中 ...

  6. 1130 - Host '' is not allowerd to connect to this MySQL server,

    是因为缺少访问权限,在MySQL ->User表里 执行 INSERT INTO `user` VALUES ('%', 'root', '*81F5E21E35407D884A6CD4A731 ...

  7. 汇编文件后缀.s与.S

    转载:http://www.cnblogs.com/IamEasy_Man/archive/2011/08/10/2134212.html 一.大小写后缀的区别: .s:  汇编语言源程序;汇编 .S ...

  8. Linux下多个.c文件的编译和Makefile文件

    在编程的时候,我们可以把一个完整程序的每个函数分离出来,写成.c文件,最后再一起编译和链接.这样有利于程序功能模块化,也方便检查代码错误. .h文件:里面编辑该程序需要引用的头文件. #ifndef  ...

  9. CSS实现文本超过指定长度显示省略号

    <style type="text/css"> li { width:200px;/*宽度,超过即会溢出*/ line-height:25px;/*设置行间距*/ te ...

  10. DOS命令安装配置Apache + MySQL + PHP 开发环境 (VC11)

    一.下载 1.下载Apache 下载地址:https://www.apachelounge.com/download/VC11/ 2.下载MySQL 下载地址:http://dev.mysql.com ...