前提条件
我认为看我这篇文章都是对msvc、cmake有一定了解的用户,因此会讲的比较简洁,在看下面的内容之前你的系统里必须装有cmake(终端里输入cmake必须有输出)、vs(只有编译套装即可),我使用的配置如下:
- Cmake 3.17,msvc-14.1(vs2017),Boost 1.74.0(下文会讲如何安装)
我这篇文章最想强调的一点是:在Windows上,尽量不要使用Findxxx.cmake(不管是第三方作者写的还是cmake自己提供的)。比如boost,cmake自己提供了FindBoost.cmake,但是它是个半残品,一些需要使用的变量在find_package之后还是空的。每个项目都会提供xxxConfig.cmake,我们直接使用find_package的config模式直接调用项目原生的xxxConfig.cmake会少很多问题。
获得Boost库
如果需要编译安装,可以参考这篇文章c++ - 使用Boost,关键的地方就是指定使用的python的信息。这里需要注意的是,如果需要编译64位版本,bootstrap.bat(你在boost文件夹下先执行bootstrap.bat才能生成b2.exe)和b2.exe这两个命令都必须在VS提供的64位命令行执行。虽然此时终端还是显示address-model:32-bit,但是生成的就是64位的库文件。
另一种方法是直接上Prebuilt windows binaries(boost官网提供的下载地址),下载预编译好的库文件,这里有点不方便的地方是不知道它支持的python版本,如果你对python版本有特殊需求,先下载项目中的DEPENDENCY_VERSIONS.txt看下。
我下载之后安装的路径是E:/source/boost_1_74_0,这个版本的boost支持python3.8,所以要保证系统中有python3.8,我喜欢的方法是下载miniconda后create env,这样不管我下载的是什么预编译版本都能很快切换对应的版本。
CMakeLists.txt编写
- 新建文件夹hello,在其中新建文件main.cpp,内容如下:
#define BOOST_PYTHON_STATIC_LIB
这里定义宏变量BOOST_PYTHON_STATIC_LIB,是因为编译的时候希望链接boost的python静态库,编译器默认采用动态连接,这样的话你生成的库文件位置还必须有“boost_python38-vc141-mt-x64-1_74.dll”(boost的lib64-msvc-14.1文件夹下的动态库文件),这样才能import成功,比较麻烦。
- 编写CMakeLists.txt
cmake_minimum_required
set(Boost_USE_STATIC_LIBS ON)是为了和上面说的使用boost静态库对应,如果这里设置为OFF则main.cpp不需要定义那个宏。
windows下不像linux下有默认的公共头文件和安装目录,所以windows下的CMakeLists.txt在find_package之前需要先告诉去哪里找Findxxx.cmake或者xxxConfig.cmake,这里设置了Boost_DIR之后(不止如此,任何库都是设置xxx_DIR),cmake就知道在这个文件夹下寻找BoostConfig.cmake,同时find_package里面也可以看到我设置为config模式,这样就不会调用cmake自己的FindBoost.cmake。
PYTHON_INCLUDE_DIRS和PYTHON_LIBRARIES两个变量需要自己确定一下路径,我下载的miniconda默认使用的是python3.8,所以直接在最上层目录,如果你是create env之后的python,应该在envs文件夹下去寻找。
最后,我们的目标文件是一个动态链接库,所以是add_library(xxxxx SHARED xxxxx)格式,set_target_properties(hello PROPERTIES SUFFIX ".pyd")的作用是将生成的动态链接库后缀名从默认的.dll改成.pyd,这样改的原因是python不能识别后缀名.dll,你当然可以直接手动改成.pyd,但是这样就比较麻烦。
- 编译生成动态链接库
以下命令必须在vs提供的命令行里,或者你保证在当前命令行里能够使用cl.exe,nmake.exe。
mkdir build
cd build
cmake -G "NMake Makefiles" ..
make
此时文件夹下会生成hello.pyd,import hello没报错就代表成功了。
![f83e854631e921c5cc850aa600b4023e.png](https://i-blog.csdnimg.cn/blog_migrate/440eab14505160535cf0c31421b06e4a.jpeg)
![7caf63746874168ac3d55270d38935cf.png](https://i-blog.csdnimg.cn/blog_migrate/ce63962cdb621f661bd75d83588bba43.jpeg)
![c47d658d1a4bf88a663e68a7cf64b01e.png](https://i-blog.csdnimg.cn/blog_migrate/ea287500630975b7f1000199db19a818.png)