使用Cython编译动态链接库
软硬件环境
ubuntu 18.04 64bit
anaconda with python 3.6
cython 0.27.3
cython简介
Cython是让Python脚本支持C语言扩展的编译器,是python的超集,Cython能够将Python和C混合编码的.pyx脚本转换为C代码,主要用于优化Python脚本性能或Python调用C函数库。由于Python固有的性能差的问题,用C扩展Python成为提高Python性能常用方法。本文主要是介绍如何使用cython将python代码编译成C语言中的动态链接库,也就是常说的so。
cython安装
使用pip进行安装
1pip install cython
准备python模块
1cd /home/xugaoxiang/anaconda3/lib/python3.6/site-packages
2mkdir djstava
3cd djstava
4touch __init__.py test.py
编辑 test.py 文件内容
1def test():
2 '''
3 Just an example.
4 '''
5 print('Hello Cython.')
接下来测试下创建的模块是否可以被导入,其中的方法是否可以正常运行。这个可以用 python 或者 ipython 来进行
1xugaoxiang@ubuntu:~/anaconda3/lib/python3.6/site-packages/djstava$ python
2Python 3.6.4 |Anaconda custom (64-bit)| (default, Jan 16 2018, 18:10:19)
3[GCC 7.2.0] on linux
4Type "help", "copyright", "credits" or "license" for more information.
5>>> import djstava.test
6>>> djstava.test.test
7<function test at 0x7ff35f135598>
8>>> djstava.test.test()
9Hello Cython.
编译成so库
1cd /home/xugaoxiang/anaconda3/lib/python3.6/site-packages/djstava
2cython test.py
生成了test.c文件,然后
1gcc -c -fPIC -I/home/xugaoxiang/anaconda3/include/python3.6m test.c
生成目标文件即.o文件
1gcc -shared test.o -o test.so
到此,动态库正式生成。
测试
这次我们用ipython来测试,首先进到目录/home/xugaoxiang/anaconda3/lib/python3.6/site-packages/djstava,将test.py文件删除,防止它形成干扰
1xugaoxiang@ubuntu:~/anaconda3/lib/python3.6/site-packages/djstava$ ipython
2Python 3.6.4 |Anaconda custom (64-bit)| (default, Jan 16 2018, 18:10:19)
3Type 'copyright', 'credits' or 'license' for more information
4IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.
5
6In [1]: import djstava.test
7
8In [2]: djstava.test.test
9Out[2]: <cyfunction test at 0x7f90945bbc80>
10
11In [3]: djstava.test.test()
12Hello Cython.
另外,python中如何去调用so库,请见之前的文章https://xugaoxiang.com/20
结合setup.py使用
如果还不了解setup.py的话,请移步https://xugaoxiang.com/144。为了跟上面的工程相冲突,我们新建一个新的目录/home/xugaoxiang/test,然后创建文件test.pyx,pyx文件允许C和python进行混编,它的内容如下
1def test():
2 '''
3 Just an example.
4 '''
5 print('Hello Cython.')
编写setup.py文件
1from distutils.core import setup
2from Cython.Build import cythonize
3
4setup(
5 name='Test pyx',
6 ext_modules=cythonize('test.pyx')
7)
编辑完毕,开始安装
1xugaoxiang@ubuntu:~/test$ python setup.py build
2Compiling test.pyx because it changed.
3[1/1] Cythonizing test.pyx
4running build
5running build_ext
6building 'test' extension
7creating build
8creating build/temp.linux-x86_64-3.6
9gcc -pthread -B /home/xugaoxiang/anaconda3/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/xugaoxiang/anaconda3/include/python3.6m -c test.c -o build/temp.linux-x86_64-3.6/test.o
10creating build/lib.linux-x86_64-3.6
11gcc -pthread -shared -B /home/xugaoxiang/anaconda3/compiler_compat -L/home/xugaoxiang/anaconda3/lib -Wl,-rpath=/home/xugaoxiang/anaconda3/lib -Wl,--no-as-needed -Wl,--sysroot=/ build/temp.linux-x86_64-3.6/test.o -o build/lib.linux-x86_64-3.6/test.cpython-36m-x86_64-linux-gnu.so
编译后的文件目录结构如下
1xugaoxiang@ubuntu:~/test$ ls -R
2.:
3build setup.py test.c test.pyx
4
5./build:
6lib.linux-x86_64-3.6 temp.linux-x86_64-3.6
7
8./build/lib.linux-x86_64-3.6:
9test.cpython-36m-x86_64-linux-gnu.so
10
11./build/temp.linux-x86_64-3.6:
12test.o
注意到,test.c文件已经生成,同时还有build下的.o及.so文件。同样的,我们用ipython来测试下生成的so文件,在当前目录下创建一个全新的文件夹,然后将上步中生成的so文件拷贝过来,再新建一个__init__.py文件,内容是
1from test import *
然后开始测试
1xugaoxiang@ubuntu:~/test/test$ ipython
2Python 3.6.4 |Anaconda custom (64-bit)| (default, Jan 16 2018, 18:10:19)
3Type 'copyright', 'credits' or 'license' for more information
4IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.
5
6In [1]: import test
7
8In [2]: test.test()
9Hello Cython.
参考资料
http://cython.org/
https://docs.python.org/3/extending/extending.html
https://stackoverflow.com/questions/24226001/importerror-dynamic-module-does-not-define-init-function-initfizzbuzz
https://cython.readthedocs.io/en/latest/src/reference/compilation.html
更多推荐



所有评论(0)