当前位置: 首页 > 后端技术 > Python

C-如何快速生成Python的C扩展,md

时间:2023-03-25 20:01:21 Python

原文地址:https://blog.52sox.com/shi-yo...前言好久没分享技术文章了,主要是自己的文章太小众了,没想到分享这样一篇文章。这样一篇文章,浓缩了我这些年项目开发的实践经验。不得不说Python是一门非常优秀的编程语言。有时候,为了项目代码的安全,我们会尝试使用Python提供的CAPI编写一些源代码,然后编译成Python模块,这样就可以直接在Python中调用了。编译的一些技巧对于Python的CAPI编写的代码,如果快速生成对应Python的扩展库,比如Linux下的.so,Windows下的.pyd。主要有以下几种方法:使用setuptools模块使用scikit-build模块使用cmake其实这些方法经常一起使用。手动编写setup.py文件,指定导入对应的头文件和链接库,不建议大中型项目使用。在setuptools方法之前,先用下面的方法生成一个C源文件:pipinstallpyd-tplpyd-tplhello这个模块是自己写的一个用于快速生成PythonC扩展文件的库。安装完成后,我们调用pyd-tpl命令在当前目录下生成一个hello.c源文件和一个setup_hello.py文件。我们可以直接执行下面的方法编译生成一个hello模块:pythonsetup_hello.py这是第一种使用setuptools生成模块的方法。下面主要介绍后两种方法。scikit-build方法首先,我们运行如下命令安装相应的库:pipinstallscikit-buildcmake由于scikit-build依赖cmake,我们可以直接使用pip安装该工具。安装完成后,我们在setup.py中写入如下代码:fromskbuildimportsetup后,在工程目录下新建一个CMakeLists.txt,其内容如下:cmake_minimum_required(VERSION3.11.0)project(helloVERSION0.1.0)find_package(PythonExtensionsREQUIRED)add_library("${PROJECT_NAME}"MODULEhello.c)python_extension_module("${PROJECT_NAME}")install(TARGETShelloLIBRARYDESTINATIONhello)这里我们将项目名称设置为hello,通过使用cmake提供的find_package指令查找Python扩展。然后通过add_library编译hello.c文件,生成以工程名命名的模块。然后需要在项目目录下创建pyproject.toml文件,文件内容如下:[build-system]requires=["setuptools","wheel","scikit-build","cmake","ninja"]之后,我们可以运行如下命令来实现整个过程的自动编译:pythonsetup.pybuild但是这种方式有一个缺点,如果系统不能正常识别你的编译器,比如在Windows下,我使用VisualStudio2015,它不能很好地识别它。只能在VisualStudio2015工具提供的菜单窗口下运行。流程如下图所示:cmakenative模式从cmake3.12版本开始,提供了一个非常好用的Python_add_library命令,具体可以参考。借助这个命令,我们可以快速生成Python的C扩展。我们只需要修改上面CMakeLists.txt中的内容如下:cmake_minimum_required(VERSION3.12.0)project(helloVERSION0.1.0)find_package(Python3COMPONENTSDevelopment)include_directories(${Python3_INCLUDE_DIRS})Python3_add_library(helloMODULEhello.c)命令语法与add_library命令相同。在这里,我们使用的是Python3,所以使用find_package命令中指定的Python3。然后在Windows下创建build目录,进入该目录执行以下命令:mkdirbuildcdbuildcmake-G"VisualStudio142015"-Ax64..cmake--build。--configReleaseForLinux,将对应的命令修改为:cmake..make通过cmake工具,这样我们就可以轻松生成Python的hello.pyd和hello.so对应的C扩展。其实还有一种生成PythonC扩展的方法,就是将cmake和setup.py文件结合起来,通过setup.py文件中setup函数的cmdclass参数指定一个自定义的cmake编译类。其实在实际的项目开发中,真的没有必要弄的那么复杂。把一个非常简单的问题复杂化是得不偿失的。这里就不介绍了,使用上面三种方法可以轻松解决Python的C扩展编译问题。其中,第三种方法最为推荐。