利用boost.python庫實現C++與Python的整合

Wray_Zheng發表於2017-06-04

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 目錄下,然後執行命令:

b2 toolset=msvc-14.0 --with-python variant=debug runtime-debugging=on link=static --user-config=user-config.jam stage複製程式碼

該命令會根據上面的配置檔案,生成需要用到的靜態庫檔案。

二、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 語句)。

#define BOOST_PYTHON_STATIC_LIB複製程式碼

例如有這麼一個 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

版權宣告

作者:Wray Zheng
原文連結: www.codebelief.com/article/201…

相關文章