fastapi系列还没搞完, 又开了个新坑。fastapi暂时因为没啥项目,所以没什么好更新的,然后自己在手写一个fastapi 的二次开发框架,主要是带user和权限管理相关的东西,减少部分代码的开发。
今天主要是讲cython的一些功能,之后fastapi的部分代码需要拥戴cython,进行加密处理或者提高运行速度都是极好的。对于对c/c++不熟悉的还是有一定帮助的。(注意,在windows上使用cython可能会失败)(最好的学习方式其实是看别人写的代码。。)
setup.py写第三方扩展包主要是使用extension来进行,但是这一块网上的讲解都比较简单。其实主要还是涉及到动态链接库和相对路径这一块很坑。
这里从路径开始讲解。(想要知道怎么写代码的请移步cython官方文档,这里主要是对官方文档没讲到的地方进行扩充)
参考:
https://www.coderclan.cc/198.html
https://blog.csdn.net/xinyu391/article/details/88804818
https://blog.csdn.net/xianxjm/article/details/73609142
https://blog.csdn.net/test1280/article/details/81157767
https://docs.python.org/3.6/distutils/setupscript.html#preprocessor-options
https://docs.python.org/3.6/distutils/sourcedist.html#manifest
使用setup.py编译动态链接库的时候(静态链接库没这问题),由于要调用的库是已经打包好了的,在链接器链接代码和动态库的时候,会按照这个搜索路径去搜索要使用的库:/home/hello/lib–>/usr/lib–>/usr/local/lib。官方文档在编译queue的动态库之后,需要粘贴或移动到这三个文件夹中的一个去。
对于习惯了python的相对路径的我们来说,当然更希望这些东西都在本地调用(代码执行的地址),或者直接在安装之后的包路径里面调用,总之就是不想放到他指定的地方去(捂脸哭)。
所以在Extension的参数里面需要增加如下参数:-Wl,-rpath=sopath
,sopath是链接器的路径,目前我这边遇到的问题就是,so文件没办法放到包里面,但是又不想粘贴到各自的文件,所以想把.so文件和代码打包放在一起,目前只能做到文件setup.py安装之后能正常运行。。。
之后考虑把so文件也放到包里面
代码编译如下:
from setuptools import Extension, setup
from Cython.Build import cythonize
ext_modules = cythonize([
Extension("chello", ["test.pyx"],
libraries=["hello"],
extra_link_args=['-Wl,-rpath=c/lib'],#一定要加,让运行时候链接器知道去哪儿找文件
include_dirs=['c2/include'],
library_dirs=['c2/lib']
),
])
setup(name='chello', ext_modules=ext_modules,)
链接器的一些参数说明:
参考:https://blog.csdn.net/xianxjm/article/details/73609142
首先这几个命令一般用在gcc/g++或makefile中,但是一般的IDE里也会涉及。只是在IDE里的配置方式会不同,有的是配置文件如QtCreator,有的是图形化界面,如CodeBlocks。无论是什么样的方式其本质都是一样的,尤其是配一个工程的时候,这些都是必不可少的。
-I,添加包含路径
-I 在编译时用,告诉编译器去哪个路径下找文件
如:-I /home/hello/include
表示将/home/hello/include目录作为第一个寻找头文件的目录。
编译器的寻找顺序是:/home/hello/include–>/usr/include–>/usr/local/include。如果在/home/hello/include中有个文件hello.h,则在程序中用#include
可以加多个包含路径,编译器的寻找顺序为添加的顺序。
-l,添加引用链接库
-l 在链接时用到,它的作用是告诉链接器,要用到哪个库。
如:-l pthread
告诉链接器(linker),程序需要链接pthread这个库,这里的pthread是库名不是文件名,具体来说文件句是libpthread.so。
-L,添加链接库路径
-L 后跟路径,告诉链接器从哪找库(.so文件),只有在链接时会用到。
如:-L /home/hello/lib
表示将/home/hello/lib目录作为第一个寻找库文件的目录,寻找顺序是:/home/hello/lib–>/usr/lib–>/usr/local/lib。
可以加多个包含路径,链接器的寻找顺序为添加的顺序。
-Wl:rpath,添加运行时库路径
-Wl:rpath 后面也是路径,运行的时候用。这条编译指令会在编译时记录到target文件中,所以编译之后的target文件在执行时会按这里给出的路径去找库文件。
如:-Wl:rpath=/home/hello/lib
表示将/home/hello/lib目录作为程序运行时第一个寻找库文件的目录,程序寻找顺序是:/home/hello/lib–>/usr/lib–>/usr/local/lib。
可以加多个包含路径,程序在运行时的寻找顺序为添加的顺序。
一开始我认为编译路径和运行路径应该是一样的才对,为什么要分两个?实际上在配置工程的时候为了标准化,编译出的target(.so或是可执行文件)不一定跟源文件(main.cpp,XX.cpp)放在一个文件夹下。如不在一个文件夹下,在编译时,-L后面跟的是相对于源文件的路径,-Wl:rpath后面跟的是相对于target(.so或是可执行文件)的路径,确切来说是相对于工作目录的路径。QtCreator的工作路径就是target文件的路径,Codebloks的工作路径是.cbp文件的路径。所以不同的IDE在配置有时候会一些细微不同,这些不同一不注意就会有大坑。