参考链接: 如何在Python中调用C函数

目录

编写Python扩展1. 创建应用代码2. 根据样板编写封装代码2.1 包含Python头文件2.2 为每一个模块函数添加形如PyObject* *Module_func()* 的封装函数2.3 为每一个模块函数添加一个PyMethodDef *ModuleMethods[]* 数组/表2.4 添加模块初始化函数

3 编译并测试3.1 创建 setup.py3.2 运行 setup.py 来编译并链接代码3.3 在Python中导入模块3.4 测试函数

4. 文档扩展4.1 在2.2中出现的 `int PyArg_ParseTuple(PyObject *arg, const char *format, ...);` 函数Python和C/C++之间的“转换编码”取自文档的例子:文档1.7部分

4.2 在3.1中创建的`setup.py` 。

编写Python扩展

1. 创建应用代码

编写一个比较简单的函数,求阶乘。并且写上main函数进行测试。   编译测试

$ gcc Extest1.c -o Extest

$ ./Extest

4! = 24

2. 根据样板编写封装代码

先给个文档地址:Extending Python with C or C++

2.1 包含Python头文件

在大多数类UNIX系统上,Python包含文件一般位于/usr/local/include/python2.x 或者 /usr/include/python2.x 中。我的系统是ubuntu 18.04 LTS。没有python2,系统自动安装的只有python3。我的位于 /usr/include/python3.6 中 将Python.h 这个头文件包含在源码中

#include "Python.h"

这边之后编译这个文件时可能会出现错误 fatal error: Python.h: No such file or directory compilation terminated. 。 stack overflow上的解决方案

sudo apt-get install python3-dev

2.2 为每一个模块函数添加形如PyObject* Module_func() 的封装函数

对于每个需要在Python环境中访问的函数,需要创建一个以static PyObjuec* 标识,以模块名开头,紧接着是下划线和函数名本身的函数。例如,若要让 fac() 函数可以在Python中导入,并将Extest 作为最终的模块名称,需要创建一个名为Extest_fac 的封装函数。在用到这个函数的Python脚本中,可以使用import Extest 和 Extest.fac() 的形式在任意地方调用fac() 函数。封装函数的任务是将Python中的值转成C形式,接着调用相应的函数。当C函数执行完毕时,需要返回Python的环境中。封装函数需要将返回值转换成Python形式,并进行真正的返回,传回所有需要的值。

2.3 为每一个模块函数添加一个PyMethodDef ModuleMethods[] 数组/表

这边书里《Python核心编程》和文档稍微有点出入,书里是3个参数,文档是4个参数,但是文档没有写第4个参数是什么,所以这边先按书里写的。

2.4 添加模块初始化函数

书里是这么写的,我怀疑是python2和3的区别,所以这里书里的不太对,我这边在后面的运行中会出现问题,所以这里稍微改一下。用文档的内容。 文档里的初始化格式:

3 编译并测试

3.1 创建 setup.py

3.2 运行 setup.py 来编译并链接代码

运行该命令构建扩展

python3 setup.py build

Error 1: 找不到python.h。解决方案见上Error 2: 用书里的函数会显示没有initModule这个函数。解决方案见上Error 3: 显示找不到distutils 模块No module named 'distutils.core'。解决方案

sudo apt-get install python3-distutils

3.3 在Python中导入模块

扩展模块会创建在build/lib.*目录下,即运行setup.py脚本的位置。要么切换到这么目录中,要么用下面的方式将气安装到Python中。

$ python3 setup.py install

Error 这里有了问题,注意最后一行Permission denied ,所以这里用 sudo python3 setup.py install 就可以了。

3.4 测试函数

4. 文档扩展

4.1 在2.2中出现的 int PyArg_ParseTuple(PyObject *arg, const char *format, ...); 函数

函数文档 1.7在fac()的示例中,当客户程序调用Extest.fac()时,会调用封装函数。这里会接受一个Python整数,将其转换成C整数,接着调用C函数fac(),获取返回结果,同样是一个整数。将这个返回值转换成Python整数,返回给调用者(记住,编写的封装函数就是def fac(n)声明的代理函数。当这个封装函数返回时,就相当于Python fac()函数执行完毕了)。如何完成转换?Python -> C : PyArg_Parse*(). C->Python : Py_BuildValue()PyArg_Parse*() : 类似于C中的sscanf 函数。接受一个字节流,然后根据一些格式字符串进行解析,将结果放入到相应指针所指的变量中。若解析成功就返回1;否则返回0.Py_BuildValue() :类似于 sprintf 函数,接受一个格式字符串,并将所有参数按照格式字符串指定的格式转换成一个Python 对象。

Python和C/C++之间的“转换编码”

格式编码Python数据类型C/C++数据类型s, s#str/unicode, len()char*, intiintintbintcharcstrchardfloatdoublehintshortlintlong

取自文档的例子:文档1.7部分

#include "Python.h"

int ok;

int i, j;

long k, l;

const char *s;

Py_ssize_t size;

ok = PyArg_ParseTuple(args, ""); /* No arguments */

/* Python call: f() */

ok = PyArg_ParseTuple(args, "s", &s); /* A string */

/* Possible Python call: f('whoops!') */

ok = PyArg_ParseTuple(args, "lls", &k, &l, &s); /* Two longs and a string */

/* Possible Python call: f(1, 2, 'three') */

ok = PyArg_ParseTuple(args, "(ii)s#", &i, &j, &s, &size);

/* A pair of ints and a string, whose size is also returned */

/* Possible Python call: f((1, 2), 'three') */

{

const char *file;

const char *mode = "r";

int bufsize = 0;

ok = PyArg_ParseTuple(args, "s|si", &file, &mode, &bufsize);

/* A string, and optionally another string and an integer */

/* Possible Python calls:

f('spam')

f('spam', 'w')

f('spam', 'wb', 100000) */

}

{

int left, top, right, bottom, h, v;

ok = PyArg_ParseTuple(args, "((ii)(ii))(ii)",

&left, &top, &right, &bottom, &h, &v);

/* A rectangle and a point */

/* Possible Python call:

f(((0, 0), (400, 300)), (10, 10)) */

}

4.2 在3.1中创建的setup.py 。

官方文档在这里Writing the Setup Script

参考书籍: 《Python核心编程》Unit8 百度网盘链接:https://pan.baidu.com/s/1XYSY65_BuQkEHm-LFzzi3g 提取码:awqc 《Python3文档》https://docs.python.org/3/ 这篇文章主要需要用到的文档内容上面已经给了

[转载] 扩展Python之在Python中调用C编写的函数模块相关推荐

  1. python 在一个py文件中调用另一个py文件中的变量以及一个有趣的问题

    python 在一个py文件中调用另一个py文件中的变量以及一个有趣的问题 1.在一个py文件中调用另一个py文件中的变量 新建一个py文件,记为t1.py # t1.py m = 2 n = 1 a ...

  2. Python如何在main中调用函数内的函数

    Python如何在main中调用函数内的函数 一般在Python中在函数中定义的函数是不能直接调用的,但是如果要用的话怎么办呢? 一般情况下: def a():#第一层函数def b():#第二层函数 ...

  3. java怎么调用存储函数_java中调用存储过程或存储函数的方法

    java中调用存储过程或存储函数的方法 1.调用存储过程:CallableStatement clstmt = null;try {clstmt = conn.prepareCall("{c ...

  4. java 执行oracle 存储过程_oracle--在java中调用存储过程和存储函数

    在java中调用存储过程和存储函数 存储过程: 查询某个员工的姓名 月薪 职位: create or replace procedure queryempinfo(eno in number, pen ...

  5. python configure函数 循环_使用python统计git仓库中频繁修改的热点函数

    本篇博客以开源代码RT-Thread为例,描述了如何使用python扫描统计代码中频繁修改的函数,帮助我们发现系统中需求变化和BUG制造的重灾区. 需求背景 最近在学习设计模式时,印象深刻的一句话就是 ...

  6. 在全局中调用类的静态成员函数

    在全局中直接调用类的静态成函数会产生重复声明错误. 例如: FooClass::FooStaticFunction(); 如果在全局中间接调用类的静态成员函数则不会产生错误,但是会产生多余的全局变量. ...

  7. vs2013 c# 中调用 c 编写的dll出错的可能错误

    先说出错原因:    堆栈调用顺序  解决办法:     使用   __stdcall 或 使用C#属性 CallingConvention 起因是我想在c#中调用c函数结果出错了 如下 C 头文件 ...

  8. 在一个PHP中调用另一个php函数,php调用函数 php如何调用函数?

    php如何调用函数? 1.递推 2.回归递推: 递推为正向的推导,即从前向后的分析问题,寻找递推的条件. 1-3求和为例 sum(1) = 1 0 sum(2) = 2 1 sum(3) = 3 2 ...

  9. 如何在matlab sfunction 函数中调用自己写的函数?

    自己编写了一个s函数,有几个参数引用了自己写的几个函数,在脚本中可以正确运行,但在写成s函数,进行 simulink 仿真的时候,已知提示"too many input auguments& ...

最新文章

  1. 一个简单的PHP模板引擎
  2. Python matplotlib中文显示异常,导入simhei字体有误
  3. 【渝粤教育】广东开放大学 土木工程材料 形成性考核 (22)
  4. VS.NET提示试图运行项目时出错:无法启动调试。绑定句柄无效解决办法
  5. 多表关联查询_【函数007】 EXCEL多表关联查询实战
  6. MySQL事务处理特性的实现原理
  7. 十进制数怎样转成十六进制数
  8. codevs 1683 车厢重组
  9. 【转】解密微软的架构师之路
  10. tiledmap 图块属性_TiledMap 组件参考
  11. mac 重装 mysql
  12. 手把手学习Vue3.0:CSS样式基础和HTML5基础收藏
  13. 工作中的Linux防火墙心得
  14. 特斯拉 开源_开源与癌症作斗争,特斯拉采用Coreboot,Uber和Lyft发行开源机器学习...
  15. axis调用webservice不同参数的方法
  16. 漫谈OCL概念、特征和实践(作者:大雁北飞)
  17. IE和Firefox浏览器CSS网页布局不同点
  18. Excel怎么设置密码保护工作表
  19. android 手机文件及文件夹目录详解
  20. 第9章第9节:完成过渡页幻灯片版式的制作 [PowerPoint精美幻灯片实战教程]

热门文章

  1. NYOJ1 - A+B Problem
  2. html实现在线新闻浏览器,使用JQuery Mobile实现手机新闻浏览器
  3. JavaScript的String对象使用
  4. Go语言基础进阶—程序结构—包和文件
  5. CTF之Web安全训练前篇1
  6. 圆方树(bzoj 2125: 最短路)
  7. 牛客网暑期ACM多校训练营(第三场): A. Ternary String(欧拉降幂+递推)
  8. 牛客网暑期ACM多校训练营(第三场): E. Sort String(KMP)
  9. Mysql用户权限管理:Grank和Revoke
  10. 运算符重载的非成员函数形式