Python扩展(Cython混编)

  • 背景介绍
    Cython是一种针对Python语言与Cython扩展语言进行优化的静态编译器通过编写Cython接口代码,可以让Python代码与C/C++代码无缝衔接,达到为Python加速的目的。当然,也可以完全通过Cython接口重构Python代码,直接提速Python。整个过程可以表示为:首先将Cython接口代码转化为C/C++代码,然后将C/C++代码编译为动态链接库.pyd(Windows下)或.so文件(Linux下),即:
    Cython接口代码 $\rightarrow$ C/C++代码 $\rightarrow$ .pyd/.so动态库
    如果接口编写得当,通过Python调用该动态库文件较原生Python代码可提速两个量级。
    在语法层面,Cython几乎支持所有的Python语法,并且额外加入了一些C/C++的等效写法(提速的关键)。因此,在编写接口代码的时候势必两种写法都会用到,从而造成混乱。本文将主要介绍笔者习惯的Cython接口写法规范,可能会比较抽象。关于语法细节,建议参考官方文档:https://cython.org/

  >>>使用规范<<<

  • Python接口端实现Cython与Python之间的交互支持缺省参数
    • def $\rightarrow$ 函数接口
    • cdef class $\rightarrow$ 类接口
      此种情况下,类对象中self只能索引已存在的对象,不能直接创建新内容,功能上与this指针基本对标,此即self限制(只能索引已经定义的对象)。
    注意,不建议采用纯粹的class作为接口(因为健康的Python语法解除了对self的限制,从而无法与this指针对标,进而找不到C++对象并无法与C++对象直接映射),此种用法可以作为纯Python加速方案考虑。Python接口端异常可以自动传递
  • C++接口端实现Cython与C++之间的交互不支持缺省参数
    • cdef $\rightarrow$ 函数接口
    • cdef struct $\rightarrow$ 类接口,不支持函数重载
    • cdef cppclass $\rightarrow$ 类接口,支持函数重载注意,Cython内部支持引用"&"与指针"*"操作,支持常量"const"限定(但const可以忽略)。
    注意,C++接口端异常需要手动传递推荐使用"except +")。
  • 常见操作
    • 头部编译指令
      # cython: language_level=3    # 指定Python版本
      # distutils: language=c++     # 指定C++编译
    • 加载Cython模块
      from libcpp.vector cimport vector
      from libcpp.string cimport string
      注意,vector映射Python中的Iterable对象,string映射Python中bytes对象。
    • 加载外部C++头文件及源文件
      cdef extern from '*.h':
          ...
      cdef extern from '*.cpp':
          pass
      注意,加载头文件是为了获取声明信息,加载源文件是为了获取定义信息。必须保证声明信息具有相应的定义内容(即实体)
  • 细节问题
    • setup.py文件中,sources参数必须保证加载到所有涉及到的C++源文件,但是不能重复加载;include_dirs参数可以附加包含目录
    • 当需要实例化一个C++接口下的类时,必须确保该类至少持有默认构造函数
      C++实例访问:
      直接访问 $\rightarrow$ 通过实例 $\rightarrow$ 类持有默认构造函数
      间接访问 $\rightarrow$ 通过指针 $\rightarrow$ 动态开辟空间注意内存释放(__dealloc__)
    • 采用cdef声明C++数据类型时需要注意:C++接口端类内部以及所有形参列表中均不能添加cdef关键字,其它地方均建议添加cdef关键字
      同时,无类型声明的对象默认为Python对象类型可以通过Python对象类型向接口内部传入str对象,再在合适的地方转换为bytes对象
    • 采用bint类型代替bool类型
    • Cython接口层级划分参考:

 

posted @ 2018-12-28 17:13  LOGAN_XIONG  阅读(2612)  评论(0编辑  收藏  举报