boost.python 库提供了便捷的方法来将 C++ 中的函数、类等导入到 Python 中使用,我们只需要添加少量代码,就能 C++ 与 Python 的整合。
将 C++ 代码借助 boost.python 编译成 Python 模块之后,我们可以像导入标准模块那样,将该模块导入,在 Python 中使用 C++ 中的类来创建变量,并调用其方法。总之,我们可以很方便地在 Python 中调用 C++ 实现的功能,两者的结合,既提高了程序的运行效率,也提高了编程的效率。
boost.python 库的安装和使用的具体步骤如下。
开发环境:Windows 10、Visual Studio 2015
版本:boost.python 1.64.0
下载地址:www.boost.org/users/histo…
一、编译 boost.python 库
1、将下载下来的 boost.python 压缩包解压到 D 盘,得到 D:\boost_1_64_0
2、运行目录下的 bootstrap.bat 批处理文件,等待一会儿。
创建配置文件,用于静态库的编译,内容如下:
# Configure specific Python version.
using python : 2.7
: C:/Python27/python.exe
: C:/Python27/include #directory that contains pyconfig.h
: C:/Python27/libs #directory that contains python27.lib
: <toolset>msvc ;复制代码
这里用的是 Python2.7 版本,你需要将其中的 C:/Python27
改为你电脑中 Python 的安装路径,msvc
表示使用 Visual Studio 的工具箱。
3、打开命令行,通过 cd 命令将工作目录切换到 D:\boost_1_64_0 目录下,然后执行命令:
该命令会根据上面的配置文件,生成需要用到的静态库文件。
二、VS 工程配置
在 Visual Studio 中打开 工程属性 -> 配置属性 -> C/C++
在右侧的“附加包含目录”中添加 D:\boost_1_64_0;C:\Python27\include
,这两个目录存放了需要的头文件。
打开 工程属性 -> 配置属性 -> 链接器 -> 常规
在右侧的“附加库目录”中添加 C:\Python27\libs;D:\boost_1_64_0\stage\lib
,这两个目录存放链接阶段需要用到的库文件。
三、添加 C++ 代码
编译完 boost.python 库,并设置好VS工程项目之后,就可以对 C++ 代码进行封装了。
首先,我们需要在 C++ 代码添加一个宏定义,用于告诉 VS 我们要使用的是已经编译好的 boost.python 静态链接库,该宏定义需要放在所有代码之前(包括 #include 语句)。
例如有这么一个 C++ 函数:
char const* greet()
{
return "hello, world";
}复制代码
我们需要添加如下代码:
#include <boost/python.hpp>
using namespace boost::python;
BOOST_PYTHON_MODULE(hello_ext)
{
def("greet", greet);
}复制代码
注意,代码中的 hello_ext 是目标 Python 模块的名称,模块名需与文件名相对应。
该代码可以单独放在一个源文件中,通过 #include 来关联,也可以直接添加到已有的源代码中。如果源代码已经编译成 .lib 文件,这种情况下就可以在单独的源文件中写接口。
四、生成 dll 文件
打开 工程属性 -> 配置属性 -> 常规,在右侧的 项目默认值 -> 配置类型 中选择“动态库(.dll)”,这将使 VS 生成 dll 动态库文件,而非 exe 可执行文件。
选择 生成 -> 生成解决方案,生成 .dll 文件,将该文件复制到 Python 项目目录下,将后缀改为 .pyd,得到 hello_ext.pyd 文件,该文件即为 Python 的库文件,可直接通过 import 导入。
五、在 Python 中调用
我们可以像调用标准 Python 库那样调用我们自己生成的模块:
>>> import hello_ext
>>> print hello_ext.greet()
hello, world复制代码
附:类包装器
上面所给的例子是函数包装器的示例,如果要导出的是 C++ 中的类,则需要使用类包装器来封装接口。
例如我们要导出如下的 C++ 类给 Python 使用:
class World
{
void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};复制代码
我们需要在原有代码中添加以下包装器,从而将接口提供给 Python:
#include <boost/python.hpp>
using namespace boost::python;
BOOST_PYTHON_MODULE(hello)
{
class_<World>("World")
.def("greet", &World::greet)
.def("set", &World::set)
;
}复制代码
然后按照上述的步骤生成 .pyd 模块文件,在 Python 中调用:
>>> import hello
>>> planet = hello.World()
>>> planet.set('howdy')
>>> planet.greet()
'howdy'复制代码
总结
boost.python 库还是非常方便的,正常情况下,我们无需改变原有的代码就能将数据结构和函数导出到 Python 中。比起自己使用 python.h 库来实现 C++ 与 Python 的整合,不仅仅是一般的高效。最让我感到惊喜的是,boost.python 库还提供了诸如 boost::python::list 的数据类型,我们可以直接在 C++ 中像在 Python 中使用列表那样,将不同的数据类型添加到一个 list 中。我们也可以借助 list 类型,方便地将多个数据以列表的形式传递给 Python。
上面的步骤中,最容易出现问题的是“生成 dll 文件”这一步,可能会有库文件找不到的情况,或者符号加载失败等情况。如果遇到这些问题,请检查是否正确编译了 boost.python 库、是否在工程属性中的添加了正确的头文件路径和附加库路径、安装的 python 版本的位数与VS配置的位数是否一致等等。如果实在解决不了,可以通过 Google 来搜索解决方案,StackOverflow 上有许多关于这些问题的解决办法,也欢迎给我留言,针对遇到的问题进行交流讨论。
更多关于 boost.python 的使用说明,可以参考:Boost.Python Tutorial - 1.64.0