Cython 基本使用

cython 本质上是写cython 语言,然后通过Cython 工具转化为C代码。并且转化的C代码生成的动态链接库是可以直接作为python库用的。 因为cython在生成C代码时插入了所有 扩展为python库的必须函数借口.

# 概念

cython是 Python 与 C/C++ 的中间沟通语言

cython 是Python 与 C/C++ 的合集的修改

cython 通过引用C++的头文件,获得函数的声明,后期再链接 C++ 的obj文件, 找到对应的函数实现.

eg:

  cython -3 cy_file.pyx -o cy_file.c

1 cython 可以引用C源码,因此可以用来封装C/C++ 的源码。

2 cython 转化代码时, 会自己增加很多python 扩展API, 因此, 编译成so 可以作为python模块调用.

3 cython 可以利用python的易用性, 来写代码, 然后cython直接将其转化为C代码,这样形成的库,最后提升执行效率.

# 使用

1 封装C/C++ 动态链接库so, 形成一个模块, 扩展python

  这是通过修改 cy_file.pyx文件,

  cython 向其中 添加 #include "Python.h",

  使用Python API 修改cy_file.pyx 为调用了 Python API 的 C 源文件

  这样的 cy_file.c 就编译 链接 后的 .so  这样得到的 动态链接库.so 就是正常的so库, 同时也可以用作python的扩展模块


2 将Python 处理为C/C++语言

  cython 是 python的超集, 所以cython 中可以写任何python, 调用python库


3 使用

  1 file.h file.cc, cy_file.pyx

    file.cc 中包含正常的C/C++ 代码

    file.h 包含函数声明

    cy_file.pyx 包含C 函数引用, python代码, 直接转化为标准C 代码.


  2  使用 cy_file.pyx 引用 file.cc 中的实现函数

  cdef extern from "file.h":

      void plus(double *a, double *b, double *r, int n, int m)

  使用 python 封装函数

  def cython_plus(np.ndarray[double, ndim=2, mode="c"] a not None,

                np.ndarray[double, ndim=2, mode="c"] b not None,

                np.ndarray[double, ndim=2, mode="c"] r not None,

                times not None):

            plus( np.PyArray_DATA(a),

                 np.PyArray_DATA(b),

                 np.PyArray_DATA(r),

              a.shape[0],

              a.shape[1],

              times)

3 编译

  PYTHON3FLAGS = `python3.6-config --cflags --libs --ldflags`

  1 g++ file.cc -c -o file.o

    仅编译(-c) file.cc (目的是编译导出函数 plus 的实现)

    这里仅仅进行编译, 不做链接,不生成程序或者库

  2 cython -3 cy_file.pyx  (cy_file.c)

    转化 cython 代码为 C 代码(会包含很多python API 扩展时用的函数 --- PyInit, PyModul ..... )

  3 g++ $(PYTHON3FLAGS) cy_file.c -fPIC -c -o cy_file.o

    必须 带上 Python.h 进行编译, 不然无头文件

    !!! 这个cy_file.c 就是正常的 C源码, 可以直接使用了. 但是使用时 需要链接必备的库 --- PYTHON3FLAGS

  4 g++ --shared -o cy_file.so $(PYTHON3FLAGS) cy_file.o file.o

    链接 cy_file.o file.o 为 cy_file.so

    注意,这里 $(PYTHON3FLAGS) 一定要放在 --shared -o cy_file.so 之后.

这里介绍的都是简单一个文件的,当使用多个文件时

  1 g++ file.cc -c -o file.o

    g++ file1.cc -c -o file1.o

    g++ file2.cc -c -o file2.o

    g++ file3.cc -c -o file3.o

  2 cython -3 cy_file.pyx

  3 g++ $(PYTHON3FLAGS) cy_file.c -fPIC -c -o cy_file.o

    ar -cr cy_file.a cy_file.o file.o file1.o file2.o file3.o

    ranlib cy_file.a

    打包所有需要的C源码到 静态链接库 .a 文件中

    ar

      -c 创建库

      -r 插入文件

    ranlib 更新库

  4 g++ --shared -o cy_file.so -Wl,-soname=cy_file.so,--whole-archive cy_file.a $(PYTHON3FLAGS)

  或者

  4 g++ --shared -fPIC -o cy_file.so cy_file.o file.o file1.o file2.o file3.o $(PYTHON3FLAGS)


  注意!!!

  0 编译不需要查找引用函数的定义, 只编译自己就好了.

  1 cython -3 cy_file.pyx 生成的 C程序

    1 带有Python.h

    2 使用Python API C++ 扩展python模块的必要方法

  2 编译 file.o 等文件 不能链接 必须使用-c

  3 编译 cy_file.c 必须使用 g++ $(PYTHON3FLAGS) cy_file.c -fPIC -c -o cy_file.o

    1 $(PYTHON3FLAGS)

    2 -fPIC ???

  4 链接 $(PYTHON3FLAGS) 必须放到 --shared -o cy_file.so 之后.

你可能感兴趣的:(Cython 基本使用)