当前位置:网站首页 > 技术博客 > 正文

cyclepython



好好的为何要混合Python代码和C代码呢?原因主要有2个:

  • Python性能差,将一部分核心逻辑用C语言实现以提升整体性能
  • 希望Python能够调用一个C语言实现的系统,典型例子:OpenCV计算机视觉库

Python、C混合编程并不奇怪,Python官方就提供了Python/C API可以实现「用C语言编写Python库」,见官方文档 ,如果你点开看了你可能就会发现,这好难啊!Python/C API入门门槛太高,于是有了Cython的诞生。

Cython是基于Python/C API的,但学习Cython的时候完全不用了解Python/C API。

在Linux下通过安装。安装完毕后执行,如果输出了版本号即安装成功。

本节完整代码见这里

安装完成后,我们创建一个Hello World项目,需要创建和两个文件。

这样编译项目:,会生成以及一些没用的中间文件。 下面测试我们生成的能不能用:

完整代码见这里

如果我们已经有一个C语言的动态库、静态库,如何在Python中调用外部C库呢(本节以动态库为例)?

现有C库如下,是一个叫做cmath的库:

下面将该cmath封装为Python库,为了防止名称冲突,命名为pymath:

然后还需要写,但这里不想写了,因为本文主要使用gcc手工编译的方式。

本节完整代码见这里

本节介绍gcc这种比较原始的编译方式,是希望你能搞懂Cython如何运作。如果能掌握那么相信在日后的开发工作中各种编译、部署的问题都不太可能难倒你。

我们知道Ubuntu下Python是这样安装的:,但你可能不知道有这个东西:。 这个包安装的是Python的头文件,以Ubuntu 18.04为例,安装完成后你应该可以在找到一些头文件。

看图1-1可以看到3种方式的对比:

  • 第一条线是用Python/C API,有2个哭脸,不但代码写起来烦人,编译构建也烦人,所以我们才用Cython取代Python/C API;
  • 第二条线是我们最常用的setup.py,有2个笑脸,Cython项目最常用的方式;
  • 第三条线有1个哭脸,也是本节要讲的,如何使用gcc这种传统的方式来编译Cython项目;

主要步骤是:

  • 使用生成
  • 然后使用来生成so文件
  • 要注意头文件版本,自己用的是python2的头文件还是python3的头文件

本节完整代码见这里

C语言有很多库函数,例如:

  • libc的函数
  • math库的函数

这些库函数非常常用,所以Cython已经帮我们封装了,所以我们直接调用即可。 那么Cython到底帮我们封装了多少C库函数呢?你可以在这里 找找。 如果你需要调用的函数Cython没有封装,那么你需要自己封装,会在2.2节介绍。

现在我们看下Cython如何调用这些封装好的C库函数:

测试一下可不可以用:

本节完整代码见这里

在2.1节我们已经看到Cython能够调用C函数,Cython中定义的函数能被Python调用,因此Cython就成为了Python调用C的“桥梁”,我们把这一过程叫做wrap,实现这一功能的Cython代码叫做wrapper,见图2-1。通常wrapper可以指一段代码、一个类,甚至也能泛指一类技术。

就和C语言开发一样,Cython代码也需要:包含头文件、链接静态库/动态库。

对于这几个C结构体、函数:

希望在Cython中调用:

上面代码看出来虽然Cython可以调用C,但作为wrapper还有一个要求是将C语言自然地封装成Python风格,所以还需要下面这段代码让API更加符合面向对象:

编译:

这里只贴了创建、释放的封装。其它功能(如pop、push)见完整代码。

本节完整代码见这里

对于一些需要传入回调函数的接口,会造成调用、被调用关系的反转。在之前我们讨论的都是在Cython中调用C函数,然而回调函数使得问题变为如何让C调用Cython函数。例如现在希望封装一个这样的C函数:

为了实现回调的封装:

  • 首先需要在Cython中定义一个能被C语言调用的,这是容易的
  • 然后需要在Cython的中调用Python的回调函数(我们把它叫做),这步会比较难实现,因为C环境调用时无法将的信息传入

在图2-2展示的方案中,将存至全局变量,这样可以从全局变量取到。

2.3节中提到的方案不适用于异步场景,见下文专门章节分析异步场景。

本节完整代码见这里

就像C语言有和文件,Cython有和文件,可以帮助更好的组织、管理代码,也可以实现wrapper的复用。

本节完整代码见这里

在之前的例子中,我们把C函数的导入、Python wrapper的封装都放在了文件中,这会导致一些符号名冲突。例如:

为了解决开发中遇到的这些问题,我们可以把声明放在中,这样就多了一层命名空间,如下:

有了命名空间,在中就不会产生符号名冲突了:

C程序员手动管理内存,而Python得益于垃圾回收机制,程序员无需感知内存管理。

Cython易用的原因是它的代码跟Python几乎一样,Cython的语法是Python的「超集」,即Python代码一定是Cython代码,而Cython代码不一定是Python代码。比起Python来说,Cython多了一些跟C语言相关的语法。

写在最后:完整介绍Cython是一个庞大的工程,本文只是介绍了Cython的皮毛,若有疑问欢迎交流。

  • 上一篇: linux自动重启排查
  • 下一篇: 相似度100%图片
  • 版权声明


    相关文章:

  • linux自动重启排查2025-09-22 16:01:03
  • 服务器是软件还是硬件2025-09-22 16:01:03
  • 串口调试助手最新版本2025-09-22 16:01:03
  • post提交文件2025-09-22 16:01:03
  • c++11多线程编程2025-09-22 16:01:03
  • 相似度100%图片2025-09-22 16:01:03
  • opencv均值滤波函数2025-09-22 16:01:03
  • 双硬盘双系统的设置方法2025-09-22 16:01:03
  • vcap电容2025-09-22 16:01:03
  • java单元测试框架都有哪些2025-09-22 16:01:03