VS2019中为Python混合开发添加配置Boost环境
前言:最近研究Python调用C/C++的问题,得益于CPython的实现,理论上只要把C写成Python认识的结构就能被识别了,故查阅了相关资料。要实现Python的接口需要一些库文件和数据类型,不过后面发现Boost库可以为这个过程提供更Python地封装,所以就转向Boost的配置,只可惜学艺不精,于是乎没想到就弄了一晚上。
注:如果你掌握了Boost配置的jam语法,那么就可以直接用Boost的b2编译工具进行自动化编译了,只需引入对应头文件就行了,就不需要下述的VS当中进行编译目标库的配置了(但是我还没有成功过)。
下载
我用的是目前的最新版1.73.0:https://dl.bintray.com/boostorg/release/1.73.0/source/
检查VS
我一般是不用VS来写项目的,也就用C#的时候用到所以上面只装了C#的组件和部分手动选择的MSVC相关的组件(部分Python组件需要在win底下编译安装),结果就在下一步时踩到了坑
fatal error C1083: 无法打开包括文件: “ctype.h”: No such file or directory
fatal error C1083: 无法打开包括文件: “stddef.h”: No such file or directory
fatal error C1083: 无法打开包括文件: “stdlib.h”: No such file or directory
当时比较迷惑,明明MSVC是正常的,怎么会连标准库都没有,搜索了下这些头确实是没有,还尝试复制到了编译目录底下也没有效果,后来想了想可能是自己手动点选组件安装造成的。
解决:
在组件中加入C++开发相关组件

或者在单个组件中,选择并安装Windows 10 SDK(应该任意一个版本都可以),我选择的是最新版

又一次安装完2.2GB内容后,可算没有通用库的问题了
编译构建工具
进入到Boost的下载目录下,运行里面的bootstrap.bat开始自动初始化,稍等一段时间后,就可以看到诸如下方的成功消息了
Bootstrapping is done. To build, run:
.\b2
编译目标库
Boost是一个很大的扩展库,全部编译完不太现实,只需针对性地编译其中的Python部分,并动态链接到VS当中
如果你本机只安装了一个版本的Python,那么只需直接执行命令:
b2.exe --with-python stage --stagedir="./bin/lib64-msvc-14.2" link=static address-model=64
这里需要注意几个需要修改的地方,文件夹命名最好清晰一些,例如以上文件夹名为64位MSVC14.2编译器的目标文件,MSVC编译器的版本可能是14.0或者是14.1具体需要到VS底下去检查。最后的address-model
是用于指定64位还是32位的,很重要,这取决于你安装的Python类型,现在大多都装64位了。
在默认情况下,它会自动查找Python版本并以此为目标编译,并存储在bin文件夹中,并且其编译时指定的模式可以在目标文件的命名上体现出来,可以通过配置来指定编译的目标Python版本,只需创建一个xxx.jam,在这里是user-config-py38.jam,编辑文件内容
using python
: 3.8 # 指定Python版本,只需精确到次版本号
: "C:/Python/Python38/python.exe" # Python可执行文件路径
: "C:/Python/Python38/include" # include目录路径
: "C:/Python/Python38/libs" # libs目录路径
: <define>BOOST_ALL_NO_LIB=1
;
最后,在上述的命令后面再添加一个参数:--user-config=user-config-py38.jam
以下是我自行编译的多个Python版本:

其中的目标文件

按照命名规则来说一个分别是debug一个是release,所以真正只用到的只有一个,命名规则可以通过文末的文章链接参考。但是,如果装了numpy,则会多出两个关于numpy的链接库

配置项目
现在新建一个空项目,以Windows x64为目标平台为例。
如果要编译出Python模块,建议先把项目配置类型调为Release,生成时请使用Release
在项目配置中,将常规属性中的配置类型改为“动态库(.dll)”,在高级属性中将目标文件扩展名改为**.pyd**,然后在VC++目录中修改包含目录,boost下载的文件夹底下还有一个也叫boost的目录里面有一堆头文件的,可以先把这个目录先复制到一个固定的地方,再将这个目录所在的目录包含进去(注意是boost所在目录的位置,而不是boost这个目录本身,不然后面路径会错)
在链接器底下的附加库目录,添加刚编译的对应平台位数和版本的对象库,如“lib64-msvc-14.2-py37\lib”这个文件夹,以及在对应Python安装目录的libs底下的Python37.lib,注意这个带空格的文件路径要加引号,不过我是偷懒直接将Python37.lib复制到了目录底下,那么只需包含一个对象库路径如下:

写入内容和编译
于是乎终于可以开始写代码了,随便写了个hello world,要注意头几行的define和include,特别是第一行用于显式指定使用刚刚手动编译的静态库不然链接器会去引用动态库导致失败。
#define BOOST_PYTHON_STATIC_LIB
//#include <boost/python/module.hpp>
//#include <boost/python/def.hpp>
#include <boost/python.hpp> //只要包含这一个就行了
char const* test() {
return "rua!";
}
BOOST_PYTHON_MODULE(pyCPlus) {
using namespace boost::python;
def("test", test);
}

BOOST_PYTHON_MODULE中的pyCPlus模块名要和你最终输出的文件名(默认是项目名)一样,不然会导致import时报错
编译成功后,在输出文件夹找到生成的pyd文件,可以在这个目录下打开Python命令行,import这个模块并测试成功

参考
编译,命名规则与VS配置:C++与Python混合编程:Boost.python的安装与使用
使用g++编译以及类封装,返回参数封装相关(g++还没有成功)