欢迎访问我的网站,希望内容对您有用,感兴趣的可以加入免费知识星球。

使用Cython编译动态链接库

Python基础 迷途小书童 4年前 (2019-12-08) 4466次浏览 0个评论

软硬件环境

  • ubuntu 18.04 64bit
  • anaconda with python 3.6
  • cython 0.27.3

cython简介

Cython是让Python脚本支持C语言扩展的编译器,是python的超集,Cython能够将PythonC混合编码的.pyx脚本转换为C代码,主要用于优化Python脚本性能或Python调用C函数库。由于Python固有的性能差的问题,用C扩展Python成为提高Python性能常用方法。本文主要是介绍如何使用cythonpython代码编译成C语言中的动态链接库,也就是常说的so

cython安装

首先使用pip进行安装

pip install cython

准备python模块

我们在anaconda的默认库安装目录

cd /home/xugaoxiang/anaconda3/lib/python3.6/site-packages
mkdir djstava
cd djstava
touch __init__.py test.py

创建文件__init__.pytest.py

编辑 test.py 文件内容为

def test():
    '''
    Just an example.
    '''
    print('Hello Cython.')

接下来测试下创建的模块是否可以被导入,其中的方法是否可以正常运行。这个可以用 python 或者 ipython 来进行

xugaoxiang@ubuntu:~/anaconda3/lib/python3.6/site-packages/djstava$ python
Python 3.6.4 |Anaconda custom (64-bit)| (default, Jan 16 2018, 18:10:19) 
[GCC 7.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import djstava.test
>>> djstava.test.test
<function test at 0x7ff35f135598>
>>> djstava.test.test()
Hello Cython.

OK,至此已经创建好test模块

编译成so库

接下来利用cythontest.py转换成test.c,然后编译成动态链接库so

cd /home/xugaoxiang/anaconda3/lib/python3.6/site-packages/djstava
cython test.py

生成了test.c文件,然后使用如下命令

gcc -c -fPIC -I/home/xugaoxiang/anaconda3/include/python3.6m test.c

生成目标文件即.o文件,最后链接成动态库

gcc -shared test.o -o test.so

到此,动态库正式生成。

测试so

这次我们用ipython来测试,首先进到目录/home/xugaoxiang/anaconda3/lib/python3.6/site-packages/djstava,将test.py文件删除,以免形成干扰

xugaoxiang@ubuntu:~/anaconda3/lib/python3.6/site-packages/djstava$ ipython
Python 3.6.4 |Anaconda custom (64-bit)| (default, Jan 16 2018, 18:10:19) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import djstava.test

In [2]: djstava.test.test
Out[2]: <cyfunction test at 0x7f90945bbc80>

In [3]: djstava.test.test()
Hello Cython.

调用test模块的方法和执行的结果与test.py一模一样

另外,关于在python中如何去调用C语言动态链接库,可以参考之前的文章 https://xugaoxiang.com/2019/12/08/python-c-dymanic/

结合setup.py使用

如果还不了解setup.py的话,请移步 https://xugaoxiang.com/2019/12/08/python-setup/。为了不跟上面的工程相冲突,我们新建一个新的目录/home/xugaoxiang/test,然后创建文件test.pyxpyx文件允许Cpython进行混编,它的内容如下

def test():
    '''
    Just an example.
    '''
    print('Hello Cython.')

编写setup.py文件

from distutils.core import setup
from Cython.Build import cythonize

setup(
    name='Test pyx',
    ext_modules=cythonize('test.pyx')
)

编辑完毕,使用命令python setup.py build开始安装

xugaoxiang@ubuntu:~/test$ python setup.py build
Compiling test.pyx because it changed.
[1/1] Cythonizing test.pyx
running build
running build_ext
building 'test' extension
creating build
creating build/temp.linux-x86_64-3.6
gcc -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
creating build/lib.linux-x86_64-3.6
gcc -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

编译后的文件目录结构如下

xugaoxiang@ubuntu:~/test$ ls -R
.:
build  setup.py  test.c  test.pyx

./build:
lib.linux-x86_64-3.6  temp.linux-x86_64-3.6

./build/lib.linux-x86_64-3.6:
test.cpython-36m-x86_64-linux-gnu.so

./build/temp.linux-x86_64-3.6:
test.o

注意到,test.c文件已经生成,同时还有build下的.o.so文件。同样的,我们用ipython来测试下生成的so文件,在当前目录下创建一个全新的文件夹,然后将上步中生成的so文件拷贝过来,再新建一个__init__.py文件,内容是

from test import *

然后开始测试

xugaoxiang@ubuntu:~/test/test$ ipython
Python 3.6.4 |Anaconda custom (64-bit)| (default, Jan 16 2018, 18:10:19) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import test

In [2]: test.test()
Hello Cython.

参考资料

喜欢 (0)

您必须 登录 才能发表评论!

Ads Blocker Image Powered by Code Help Pro

Ads Blocker Detected!!!

请关闭 Adblock 等类似浏览器插件,然后刷新页面访问,感谢您的支持!

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.