python作为一种通用的编程语言,一般而言,是能够满足逻辑实现的需求的。只是在日常使用过程中,除了实现一些逻辑之外,至少还有两个方面的需求是可能需要寻求其他语言帮助的,第一个是提升运行效率,第二个是复用已有C/C++代码。python比较接近自然语言这一特性确实对使用者而言很不错,但是这带来了一个不良后果--运行速度慢。有时还需要借助多进程的方式提升运算速度,但是无论如何,python本身速度慢这件事确实改变不了,也就意味着硬件资源的利用率低。而C/C++的运行速度上的优势让我们比较愿意寻求某种方式在python中调用C/C++的程序。此外,如果并不是白手起家,而是已有大量C/C++代码实现的核心功能,那么使用python重新实现一遍是不划算的。这时将这些C/C++代码编译成python可调用的库将非常具有吸引力。本文将使用三种方式将一个简单的C程序逻辑封装成python中可调用的形式,以展示python使用C/C++扩展功能的一般方式。分别是:动态共享库调用、C扩展以及swig工具。本文的所有演示在MacOS 10.14.6操作系统中完成,Linux操作系统下应该比较容易复现,Windows可能会比较麻烦一点。

1. 动态共享库调用

将C/C++代码编译成动态共享库然后在python中调用是一种比较直观的方式。在MacOS和Linux中是生成后缀为so的文件,在windows系统成是生成后缀为dll的文件。

第一步:

首先展示一下这个简单功能的C程序代码。

核心功能函数

第二步:

这里,我们使用gcc编译器将源代码编译成动态共享库。查看编译产出,发现按照预期生成了so文件。

编译动态共享库

第三步:

接着,就可以在python中加载生成的so文件,然后调用对应的功能函数。不过还是有一点需要说明,即数据类型。使用过C/C++的同学都知道,C/C++是强类型的静态语言,也就是说在执行功能函数的时候,常常必须要保证传参的数据类型完全一致,否则程序容易崩溃。python提供了一个库ctypes来解决调用C/C++程序时的类型问题。通常,我们需要使用ctypes中提供的数据类型和转换接口,将python中的数据转换成C/C++程序中的数据类型,然后调用对应的功能函数。复杂的函数参数对于这种调用方式而言是灾难性的,因此这种方式一般适用于python与C/C++交互接口简单的情形。

python调用动态共享库

2. C扩展

为了解决上文中调用动态共享库所面临的问题,还可以使用C扩展的方式完成在python中调用C/C++程序的需求。这种方式使用了python本身提供的一组C/C++语言交互接口API,这样所做成的扩展程序并不需要像动态共享库那样显式加载文件,而是像一般的python模块那样导入即可。编程风格更加pythonic,能够实现的交互接口也更加复杂。

第一步:

下面就展示一下使用C扩展的方式需要提供的C程序源代码。

C扩展源码

第二步:

C代码中除了本次演示功能的核心之外,最主要的就是定义调用接口。正是由于在C代码中实现了一个复杂解析过程,python中调用过程就可以非常简单,与一般的python程序调用毫无差别。 C代码编写完成后还需要编写一个对应的setup.py文件,以便于编译。下面展示这个setup.py文件。

setup.py编译描述文件

第三步:

C代码和setup.py文件准备完毕之后就可以进行编译了。下面展示编译的指令,并显示编译产出的文件。

编译C扩展

第四步:

可以看到,编译产出顺利生成,接下来就可以在python中调用了。由于C扩展的so文件并不在当前的搜索目录下,因此需要修改一下sys.path这个变量。除了执行核心的功能函数之外,还可以查看模块的文档,如果需要也可以设置对应的版本号。这样就与一般的python模块一致了,用起来也比较顺手。

python调用C扩展

3. Swig工具

从上文的C扩展可以看出,C/C++的源码中需要包含python交互的解析,因此显得非常复杂。而这个过程似乎是形式化的,那么有没有什么工具可以辅助完成这个过程呢?这就是这里提到的swig工具。当然,好可以用boost中的wrap接口,但是boost本身比较沉重,在发布和共享时不太方便。

第一步:

下面我们先看一下实现所需功能的C/C++源代码。

功能源码文件内容

第二步:

然后,需要定义一个后缀为i的描述文件,用于swig工具处理源代码。由于本文所演示的功能中需要使用int类型的数组,所以在描述文件中也添加了一个相关的定义,就可以在python中定义int数组,便于调用。

swig描述文件

第三步:

使用swig指令调用上面所编写的描述文件,就可以生成针对源码的wrap接口代码。从以下的演示可以看出,这条指令生成了swig_example.py和swig_example_wrap.c两个文件。

swig生成接口代码

第四步:

接下来的步骤就跟上文中的C扩展步骤一致了,编写setup.py文件,然后编译。下面展示一个详细一点的setup.py文件,其中可以指定很多与模块相关的信息,便于形成标准的python第三方库。

setup.py编译描述文件

第五步:

编译生成对应的so文件之后,就可以在python程序中调用了。

编译swig产生的接口和源码文件

第六步:

同样的,需要先设置以下搜索路径,以便于找到该模块。这里遇到的一个问题是需要保持python调用C/C++函数的传入参数与程序中定义的参数类型一致。由于本文所演示的例子中使用了int类型的指针,那么在描述文件中定义的intp就派上了用场。下面演示了参数转换和调用的过程。从这个调用来看,似乎并不简单,其原因是参数类型的转换代码较多,而且还是只能服务于单一的数据类型转换。但这并不是一个大问题。通常在设计C/C++程序时,会提供大量简单易用的类型转换的接口,在python中也会封装一些接口,从而避免在实际调用过程中频繁编写代码进行转换。在封装完类型转换接口之后,其调用形式与C/C++源码中定义的是一致的,因此我们并不需要专门地阅读swig所生成的代码,只需要掌握一点swig描述配置即可。

调用swig方式的C扩展

到此,使用C/C++扩展python就讨论完毕。上面所描述的三种方法各有利弊,一般而言,交互接口简单的就直接使用动态共享库完成,如果调用接口比较复杂那么可以使用C扩展的方式完成,如果需要封装的C代码比较复杂,那么可以考虑使用swig工具实现,然后配合一些类型转换接口。从实际的开发经验来看,扩展python还是属于比较高阶的用法,一般的日常开发中是很少用到的。在图像处理领域,由于过去曾经积累了大量的C/C++代码,而且对计算效率的要求比较高,相对而言可能需要使用扩展python的地方稍多一点。本文的notebook版本文件在github的cnbluegeek/notebook仓库中共享,欢迎感兴趣的朋友前往下载。

c++ 调用python_闲话python 48: C/C++扩展Python与Swig工具相关推荐

  1. 如何将c语言程序封装供python调用_转:用C语言扩展Python的功能

    一.简介 Python是一门功能强大的高级脚本语言,它的强大不仅表现在其自身的功能上,而且还表现在其良好的可扩展性上,正因如此,Python已经开始受到越来越多人的青睐,并且被屡屡成功地应用于各类大型 ...

  2. python 异常处理模块_扩展Python模块系列(五)----异常和错误处理

    在上一节中,讨论了在用C语言扩展Python模块时,应该如何处理无处不在的引用计数问题.重点关注的是在实现一个C Python的函数时,对于一个PyObject对象,何时调用Py_INCREF和Py_ ...

  3. python 参数封装_扩展Python模块系列(三)----参数解析与结果封装

    在上一节中,通过一个简单的例子介绍了C语言扩展Python内建模块的整体流程,从本节开始讲开始深入讨论一些细节问题,在细节讨论中从始至终都会涉及[引用计数]的问题.首先讨论C语言封装的Python函数 ...

  4. python缩写词_扩展Python中的英语缩略词

    我把wikipedia的扩展页面压缩成python字典(见下文) 请注意,如您所料,在查询字典时,您一定要使用双引号: 另外,我在维基百科页面中留下了多个选项.你可以随意修改它.注意,对右展开的消歧将 ...

  5. 扩展Python模块系列(四)----引用计数问题的处理

    承接上文,发现在使用Python C/C++ API扩展Python模块时,总要在各种各样的地方考虑到引用计数问题,稍不留神可能会导致扩展的模块存在内存泄漏.引用计数问题是C语言扩展Python模块最 ...

  6. java怎么调用python_如何在Java中调用Python代码

    Jython(原JPython),是一个用2113Java语言写的Python解释5261器.在没有第三方模块的情况下4102,通常选择利用Jython来调用1653Python代码,它是一个开源的J ...

  7. Python实例浅谈之三Python与C/C++相互调用

    参考:http://blog.csdn.net/taiyang1987912/article/details/44779719 Python实例浅谈之三Python与C/C++相互调用 二.Pytho ...

  8. python和c学习-学习 Python与C相互调用

    缘由 稀里糊涂的,用 Python 或用 C++ Qt都能写点小程序出来.然后对Python + Qt开始有点兴趣:想学PyQt4,想了解PythonQt,也期待PySide的Windows版本.但总 ...

  9. power python_在 Power BI Desktop 中运行 Python 脚本

    在 Power BI Desktop 中运行 Python 脚本Run Python scripts in Power BI Desktop 06/02/2020 本文内容 你可以直接在 Power ...

最新文章

  1. python 权限修饰符
  2. 【最爽的日期工具包LocalDate·超爽,超实用】(Java8版本)
  3. [Leedcode][JAVA][第76题][最小覆盖子串]滑动窗口]
  4. 过去的2018年,400000粉丝用指尖投票,选出了这10本技术书
  5. Maven的Snapshot版本与Release版本
  6. .NET程序员面试指南:设计窗口程序演示八皇后问题
  7. 使用 typescript ,提升 vue 项目的开发体验(2)
  8. 压测服务器性能上不去,JAVA性能优化思路探究
  9. Android 抓包工具
  10. java走梅花桩_PGIS周中赛:梅花桩4队混战 PERO17杀饮恨 STK拿下本局
  11. VMware卸载干净彻底 VMware Workstation 静态IP配置(vm常见问题)
  12. word2vec模型深度解析
  13. 免费、无版权约束、可商用的优质图片素材网站合集
  14. MT4 获取当前订单的开单价格
  15. linux如何初始化根文件系统,搭建自己的Linux根文件系统
  16. 3. PyCharm、PyQt5、PyQt5-tools的下载安装、基于PyCharm开发PyQt5
  17. 物联网之NB-IoT技术实践开发三
  18. QtCreator插件开发(四)——QtCreator编辑器
  19. RFC3920 xmpp协议
  20. 尼泊尔宣布将重测珠穆朗玛峰高度

热门文章

  1. vue 心跳监控_Vue中WebSocket加入心跳机制
  2. python软件下载3版本-【python3下载】python3下载安装 中文版-七喜软件园
  3. 零基础学python书籍-5本好书------Python零基础到入门必读Python书籍!
  4. python基础语法手册-Python学习手册(第4版)pdf
  5. python创建txt文件并写入-python如何将数据写入本地txt文本文件
  6. 今天的语音识别,我们就用Python来做,从基础的知识到实践的运用
  7. Vue实现简单图表~满满的干货
  8. 【互联网周刊】2022年第6期摘录
  9. MFC的多国语言界面的实现
  10. vb编写各种趣味小程序_【VB小程序】来测测你的打字速度吧