Boost庫(kù)是一個(gè)可移植、提供源代碼的C++庫(kù)纺腊,作為標(biāo)準(zhǔn)庫(kù)的后備畔咧,是C++標(biāo)準(zhǔn)化進(jìn)程的開(kāi)發(fā)引擎之一。Boost庫(kù)由C++標(biāo)準(zhǔn)委員會(huì)庫(kù)工作組成員發(fā)起揖膜,其中有些內(nèi)容有望成為下一代C++標(biāo)準(zhǔn)庫(kù)內(nèi)容。在C++社區(qū)中影響甚大次氨,是不折不扣的“準(zhǔn)”標(biāo)準(zhǔn)庫(kù)。
Boost由于其對(duì)跨平臺(tái)的強(qiáng)調(diào)煮寡,對(duì)標(biāo)準(zhǔn)C++的強(qiáng)調(diào),與編寫(xiě)平臺(tái)無(wú)關(guān)幸撕。大部分boost庫(kù)功能的使用只需包括相應(yīng)頭文件即可,少數(shù)(如正則表達(dá)式庫(kù)坐儿,文件系統(tǒng)庫(kù)等)需要鏈接庫(kù)宋光。但Boost中也有很多是實(shí)驗(yàn)性質(zhì)的東西炭菌,在實(shí)際的開(kāi)發(fā)中使用需要謹(jǐn)慎。
Boost庫(kù)是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱(chēng)黑低。
——百度百科
簡(jiǎn)單來(lái)說(shuō),Boost 是一系列通用的 C++ 擴(kuò)展庫(kù)的集合克握。而 Boost.python 則是這眾多擴(kuò)展庫(kù)中的其中一個(gè),它基于 C++ 代碼提供了一套 Python 接口菩暗,可作為 C++ 與 Python 混合編程的橋梁。
Boost 庫(kù)的安裝
方式一:Boost 源碼包
首先去 Boost 官網(wǎng)下載 Boost 庫(kù):下載地址旷坦。
官方默認(rèn)只提供 Boost 的源碼包。大多數(shù)情況下(純 C/C++ 開(kāi)發(fā))塞蹭,源碼包就足夠了,我們只需要在編譯的時(shí)候引入相應(yīng)的頭文件即可。但如果你的程序需要以靜態(tài)/動(dòng)態(tài)鏈接庫(kù)的形式引入某些包岗屏,就需要自己編譯了。恰好 Boost.python 就是這樣的需求这刷,畢竟,你總不能指望直接在 python 代碼中引用 C++ 源碼吧暇屋!
我們一般會(huì)把 python 代碼之外的所有 C/C++ 外掛編譯成一個(gè) .pyd
文件,這樣就能直接在 python 代碼中調(diào)用了咐刨。事實(shí)上,.pyd
文件就是一個(gè)擁有 python 接口的 .dll
文件而涉。
Boost 源碼包的目錄結(jié)構(gòu)如下:
boost_1_68_0
+---boost
+---doc
+---libs
+---more
+---status
+---tools
+---INSTALL
+---Jamroot
+---LICENSE_1_0.txt
+---boost.css
+---boost.png
+---boost-build.jam
+---boostcpp.jam
+---bootstrap.bat
+---bootstrap.sh
+---index.htm
+---index.html
+---rst.css
其中,boost
目錄下是所有庫(kù)的頭文件(.hpp
文件)啼县,libs
目錄下則是所有庫(kù)的具體實(shí)現(xiàn)(.cpp
文件)材原。
方式二:Boost 預(yù)編譯包
Boost 源碼包如果要在本地完全編譯余蟹,可能需要幾個(gè)小時(shí)的時(shí)間。因此威酒,為了方便使用,Boost 也推出了 Windows 下的 預(yù)編譯版本兼搏。預(yù)編譯包比起源碼包多出一個(gè)子目錄沙郭,用于存放已經(jīng)編譯好的靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)。
安裝預(yù)編譯版本 boost_1_68_0-msvc-14.0-32.exe
之后的目錄結(jié)構(gòu)如下:
boost_1_68_0
+---boost
+---doc
+---libs
+---lib32-msvc-14.0 # new
+---more
+---status
+---tools
+---INSTALL
+---Jamroot
+---LICENSE_1_0.txt
+---b2.exe # new
+---bjam.exe # new
+---boost.css
+---boost.png
+---boost-build.jam
+---boostcpp.jam
+---bootstrap.bat
+---bootstrap.log # new
+---bootstrap.sh
+---index.htm
+---index.html
+---project-config.jam # new
+---rst.css
其中病线,lib32-msvc-14.0
目錄保存了所有編譯好的靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)。需要注意的是送挑,預(yù)編譯版本對(duì)編譯器種類(lèi)、版本和目標(biāo)位數(shù)(32/64)都有要求惕耕。在上述例子中,要使用這些庫(kù)司澎,必須用 msvc-14.0(即 Visual Studio 2015)且設(shè)置目標(biāo)位數(shù)為 32 位。
不同版本的預(yù)編譯包可以安裝在同一個(gè)目錄下谚殊,以支持不同的編譯環(huán)境,這樣就比較方便了嫩絮。比如在上述例子中,如果還要支持 64 位剿干,可以再下載一個(gè) boost_1_68_0-msvc-14.0-64.exe
,同樣安裝在當(dāng)前安裝目錄下怨愤。這樣安裝目錄下將多出一個(gè) lib64-msvc-14.0
子目錄,存放編譯好的 64 位的庫(kù)撰洗,其余目錄和文件均不受影響。
預(yù)編譯版本滿(mǎn)足了偷懶的需求差导,但很難滿(mǎn)足所有要求,因?yàn)橛行?kù)必須配合本地環(huán)境才能使用设褐。比如 Boost.python 就必須配合本地的 Python 版本才能使用,因此本地編譯 Boost 庫(kù)這個(gè)基本技能還是必要的助析。下面我們還是以 Boost 源碼包的使用為例進(jìn)行介紹。
本地編譯 Boost.python
在編譯之前外冀,需要確保本機(jī)已經(jīng)安裝了 Visual Studio 和 Python。
首先雪隧,我們使用命令行進(jìn)入 Boost 源碼包的安裝目錄,執(zhí)行 bootstrap.bat
腳本脑沿,將會(huì)在當(dāng)前目錄下生成 b2.exe
、bjam.exe
庄拇、project-config.jam
、bootstrap.log
四個(gè)文件措近。其中,b2.exe
熄诡、bjam.exe
就是我們編譯時(shí)要用到的命令了凰浮。這兩個(gè)命令的作用是一樣的,bjam
是老版本袜茧,b2
是升級(jí)版本。
下面就可以開(kāi)始編譯 Boost.python 了笛厦,筆者在本機(jī)所使用的命令如下:
b2.exe --with-python stage --stagedir="./bin/lib32-msvc-14.0" link=static address-model=32
編譯完成后,將在 ./bin/lib32-msvc-14.0/lib
目錄下產(chǎn)生 4 個(gè)文件:
libboost_numpy36-vc140-mt-gd-x32-1_68.lib
libboost_numpy36-vc140-mt-x32-1_68.lib
libboost_python36-vc140-mt-gd-x32-1_68.lib
libboost_python36-vc140-mt-x32-1_68.lib
其中裳凸,python 和 numpy 各 2 個(gè),帶 gd
的對(duì)應(yīng) debug 版本姨谷,反之對(duì)應(yīng) release 版本。
默認(rèn)情況下梦湘,編譯時(shí)調(diào)用的編譯器和 Python 版本是 b2/bjam 自動(dòng)搜索的。如果要指定不同的 Python 版本捌议,就需要在你的 home 目錄下新建一個(gè)配置文件 user-config.jam
(路徑為 C:\Users\xxx\user-config.jam
)。推薦直接使用 Boost 根目錄下的 tools/build/example/user-config.jam
作為模板瓣颅,稍加修改即可。例如弄捕,筆者的 user-config.jam
中對(duì) Python 的配置如下:
using python
: 3.5
: "D:/App/Python35/python.exe"
: "D:/App/Python35/include"
: "D:/App/Python35/libs"
: <define>BOOST_ALL_NO_LIB=1
;
b2/bjam 參數(shù)說(shuō)明:
b2
命令的功能強(qiáng)大,用起來(lái)也比較復(fù)雜守谓,因此在使用之前,最好先查看一下該命令的幫助:
b2.exe --help
以下是一些比較重要的參數(shù)說(shuō)明:
-
stage/install:
stage 表示只生成庫(kù)(dll 和 lib)斋荞,install 還會(huì)生成包含頭文件的 include 目錄。推薦使用 stage平酿,因?yàn)?install 生成的 include 目錄實(shí)際就是源碼包下的 boost 目錄,需要 include 的時(shí)候可以直接使用蜈彼,不需要再次生成,這樣可以節(jié)省大量的編譯時(shí)間幸逆。
-
toolset:
指定編譯器,可選的如 borland还绘、gcc、msvc-14.0(VS2015)等拍顷。如果不指定,會(huì)自動(dòng)搜索本地可用的編譯器(可查看
./project-config.jam
文件以確認(rèn))。 -
without/with:
選擇不編譯/編譯哪些庫(kù)(類(lèi)似于黑名單/白名單)电媳。
--with-python
的含義是僅編譯 python帅霜,其他的都不編譯。反過(guò)來(lái)身冀,如果用--without-python
,意思就是除了 python搂根, 其他的都編譯。with/without 參數(shù)可以多次出現(xiàn)剩愧,以限定多個(gè)庫(kù)。如果不設(shè)置 with/without 參數(shù)仁卷,默認(rèn)全部編譯,可能需要幾個(gè)小時(shí)的時(shí)間锦积!需要注意,編譯 Boost.python 需要確保本地安裝了 Python丰介,并且 python 命令已加入環(huán)境變量。
要查看 Boost 包含的所有庫(kù)哮幢,可使用以下命令:
b2.exe --show-libraries
-
stagedir/prefix:
stage 時(shí)使用 stagedir,install 時(shí)使用 prefix橙垢,表示編譯生成文件的路徑。推薦給不同的編譯環(huán)境指定不同的目錄柜某,如 Visual Studio 2015 的 x86 應(yīng)用對(duì)應(yīng)的是
bin/lib32-msvc-14.0
,x64 應(yīng)用對(duì)應(yīng)的是bin/lib64-msvc-14.0
莺琳。如果都生成到一個(gè)目錄下载慈,將沒(méi)有任何益處,徒增管理難度办铡。如果使用了 install 參數(shù)琳要,那么還將在上述指定的目錄下生成include
目錄秤茅,用于保存頭文件。 -
build-dir:
編譯生成的中間文件的路徑框喳,默認(rèn)是 Boost 根目錄下的
bin.v2
目錄,一般無(wú)需設(shè)置五垮。 -
link:
指定生成動(dòng)態(tài)鏈接庫(kù)還是靜態(tài)鏈接庫(kù),取值為
static|shared
放仗。生成靜態(tài)鏈接庫(kù)使用 static,生成動(dòng)態(tài)鏈接庫(kù)需使用 shared诞挨。如不指定,默認(rèn)使用 static惶傻。靜態(tài)庫(kù)的缺點(diǎn)是占用空間比較大,優(yōu)點(diǎn)是程序發(fā)布的時(shí)候無(wú)需附帶 Boost 庫(kù)的 dll达罗,比較整潔。推薦使用靜態(tài)庫(kù)的方式編譯 Boost.python粮揉,這樣發(fā)布程序的時(shí)候就不用 Boost 的 dll 了,并且也多占用不了太多空間扶认。 -
runtime-link:
指定運(yùn)行時(shí)是動(dòng)態(tài)還是靜態(tài)鏈接其他庫(kù)。同樣有 shared 和 static 兩種方式辐宾。如果不指定,默認(rèn)是 shared季研,一般無(wú)需設(shè)置。
-
threading:
要編譯的庫(kù)是單線(xiàn)程還是多線(xiàn)程与涡,可取值
single|multi
。如果不指定驼卖,默認(rèn)是 multi,一般無(wú)需設(shè)置酌畜。 -
variant
debug|release
,編譯 debug 版本還是 release 版本桥胞。一般與最終發(fā)布的程序是 debug 還是 release 版相對(duì)應(yīng)。如果不指定埠戳,默認(rèn)兩個(gè)都編譯,一般無(wú)需設(shè)置整胃。 -
address-model
編譯成 32 位版本還是 64 位版本,可取值
32|64
屁使。如果不指定,默認(rèn)兩個(gè)版本都編譯蛮寂。如果是編譯 Boost.python,該參數(shù)就要與本地安裝的 Python 位數(shù)相對(duì)應(yīng)酬蹋,否則編譯會(huì)出錯(cuò),因此最好設(shè)置一下范抓。
Boost 靜態(tài)庫(kù)/動(dòng)態(tài)庫(kù)的命名規(guī)則
以 Boost.python 為例,如果編譯的是靜態(tài)庫(kù)(link=static
)匕垫,將會(huì)生成單個(gè) .lib
文件:
libboost_python36-vc140-mt-gd-x32-1_68.lib
而如果編譯的是動(dòng)態(tài)庫(kù)(link=shared
),將會(huì)生成兩個(gè)文件(.lib
和 .dll
):
boost_python36-vc140-mt-gd-x32-1_68.lib
boost_python36-vc140-mt-gd-x32-1_68.dll
動(dòng)態(tài)庫(kù)雖然也生成 .lib
文件象泵,但它與靜態(tài)庫(kù)的 .lib
文件差別很大。動(dòng)態(tài)庫(kù)的 .lib
更像是對(duì) .dll
的聲明偶惠,二者的關(guān)系類(lèi)似于 .h
與 .cpp
的關(guān)系。因此忽孽,動(dòng)態(tài)庫(kù)中的 .lib
文件要比靜態(tài)庫(kù)的 .lib
文件小得多馋缅。
下面以靜態(tài)庫(kù)的命名規(guī)則為例進(jìn)行分析:
libboost_python36-vc140-mt-sgd-x32-1_68.lib
| || | | | | | || ||| | | | |
- --- ------ --- -- - - - --
1 2 3 4 5 6 7 8 9
- 靜態(tài)庫(kù)以
lib
開(kāi)頭绢淀,動(dòng)態(tài)庫(kù)開(kāi)頭沒(méi)有lib
皆的。 - 所有的庫(kù)都含有
boost
前綴。 - Boost 庫(kù)名稱(chēng)费薄,本例中為
python36
。 - 編譯器名稱(chēng)及其版本楞抡,
vc140
指的是 msvc-14.0,對(duì)應(yīng) Visual Studio 2015召廷。 - 有
mt
代表threading=multi
,沒(méi)有則代表threading=single
竞慢。 - 有
s
代表runtime-link=static
,沒(méi)有則代表runtime-link=shared
筹煮。 - 有
gd
代表 debug 版本,沒(méi)有則代表 release 版本败潦。 - 目標(biāo)位數(shù),
x32
代表 32 位劫扒,x64
代表 64 位。 - Boost 庫(kù)的版本號(hào)粟关,
1_68
代表 Boost 1.68 版本。
Boost 庫(kù)的使用
如果要在項(xiàng)目中使用 Boost 庫(kù)闷板,需要做以下兩項(xiàng)配置:
- 包含 Boost 頭文件(本例中為:
D:\ProgramFiles\boost_1_68_0
)院塞; - 鏈接 Boost 庫(kù)文件(本例中為:
D:\ProgramFiles\boost_1_68_0\bin\lib32-msvc-14.0\lib
)。
Boost 官方推薦使用 b2/bjam
命令進(jìn)行自動(dòng)化編譯拦止、鏈接糜颠,只需要編寫(xiě)一個(gè) .jam
配置文件,這種方式類(lèi)似于 make
和 Makefile
其兴。但考慮到還要學(xué)習(xí) jam
語(yǔ)法,暫時(shí)還是用 Visual Studio 手動(dòng)編譯吧元旬。
在 Visual Studio 中的具體操作如下:
- 選中當(dāng)前項(xiàng)目,點(diǎn)擊屬性按鈕匀归,依次選擇“配置屬性->C/C++->常規(guī)->附加包含目錄”,編輯并添加一條路徑:
D:\ProgramFiles\boost_1_68_0
穆端; - 選中當(dāng)前項(xiàng)目,點(diǎn)擊屬性按鈕仿便,依次選擇“配置屬性->鏈接器->常規(guī)->附加庫(kù)目錄”,編輯并添加一條路徑:
D:\ProgramFiles\boost_1_68_0\bin\lib32-msvc-14.0\lib
嗽仪。
Boost.python 的使用
要使用 Boost.python,除了上述兩項(xiàng)配置之外钦幔,還需要再添加兩項(xiàng)配置:
- 包含 Python 頭文件(本例中為:
D:\Program Files (x86)\Python36-32\include
); - 包含 Python 靜態(tài)庫(kù)文件(本例中為:
D:\Program Files (x86)\Python36-32\libs\python36.lib
)搀擂。
在 Visual Studio 中的具體操作如下:
- 選中當(dāng)前項(xiàng)目,點(diǎn)擊屬性按鈕哨颂,依次選擇“配置屬性->C/C++->常規(guī)->附加包含目錄”,編輯并添加一條路徑:
D:\Program Files (x86)\Python36-32\include
相种; - 選中當(dāng)前項(xiàng)目,點(diǎn)擊屬性按鈕寝并,依次選擇“配置屬性->鏈接器->輸入->附加依賴(lài)項(xiàng)”,編輯并添加一個(gè)文件:
"D:\Program Files (x86)\Python36-32\libs\python36.lib"
衬潦,注意要有雙引號(hào),否則可能識(shí)別不正確镀岛。
測(cè)試
準(zhǔn)備 hello world 代碼
使用官網(wǎng)給出的 hello world 示例友驮,代碼文件位于 Boost 安裝目錄下:D:\ProgramFiles\boost_1_68_0\libs\python\example\tutorial
驾锰,包括 hello.cpp
與 hello.py
兩個(gè)文件,如下:
hello.cpp
:
// 當(dāng)引入 #include <boost/python/xxx> 時(shí)椭豫,Boost 會(huì)默認(rèn)鏈接 boost_python 動(dòng)態(tài)鏈接庫(kù),
// 如果我們想要鏈接靜態(tài)鏈接庫(kù)捻悯,就需要在 include 之前加上 #define BOOST_PYTHON_STATIC_LIB
#define BOOST_PYTHON_STATIC_LIB
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
char const* greet()
{
return "hello, world";
}
BOOST_PYTHON_MODULE(hello_ext)
{
using namespace boost::python;
def("greet", greet);
}
hello.py
:
import hello_ext
print(hello_ext.greet())
我們的目的是將 hello.cpp
編譯成一個(gè) .pyd
文件(其實(shí)就是一個(gè)包含 Python 接口的 .dll
文件)今缚,然后用 hello.py
調(diào)用它。
注意:hello.cpp
中的宏定義 #define BOOST_PYTHON_STATIC_LIB
非常重要姓言,它可以指定鏈接 boost_python 的靜態(tài)庫(kù),而不是默認(rèn)的動(dòng)態(tài)庫(kù)何荚。
如果你在編譯過(guò)程中遇到了這樣的錯(cuò)誤:LINK : fatal error LNK1104: cannot open file "boost_python36-vc140-mt-x32-1_68.lib"
,但是你明明已經(jīng)引入了靜態(tài)庫(kù):libboost_python36-vc140-mt-x32-1_68.lib
餐塘,你可能會(huì)納悶:我明明已經(jīng)導(dǎo)入了靜態(tài)庫(kù),為什么還找我要?jiǎng)討B(tài)庫(kù)戒傻?那么最可能的原因是,你的 C++ 代碼中漏掉了這句宏定義需纳。
使用 Visual Studio 構(gòu)建 hello world
Boost 官方推薦使用 b2/bjam
命令進(jìn)行自動(dòng)化編譯、鏈接不翩,只需要編寫(xiě)一個(gè) .jam
配置文件,這種方式類(lèi)似于 make
和 Makefile
口蝠。但考慮到還要學(xué)習(xí) jam
語(yǔ)法,暫時(shí)還是用 Visual Studio 手動(dòng)編譯吧亚皂。
- 首先使用 Visual Studio 創(chuàng)建一個(gè)空項(xiàng)目。
- 打開(kāi)項(xiàng)目屬性灭必,在“配置屬性->常規(guī)”中狞谱,進(jìn)行以下修改:
- 配置類(lèi)型設(shè)為:“動(dòng)態(tài)庫(kù)(.dll)”跟衅。
- 目標(biāo)文件名設(shè)為:
hello_ext
。
注意:.pyd
文件的名稱(chēng)必須與要導(dǎo)出的 python module 名稱(chēng)一致伶跷,否則 python 的 import 語(yǔ)句將會(huì)報(bào)錯(cuò):ImportError: dynamic module does not define module export function
。 - 目標(biāo)文件擴(kuò)展名設(shè)為:
.pyd
叭莫。
- 將
hello.cpp
文件導(dǎo)入項(xiàng)目。 - 參照上一節(jié) [Boost 庫(kù)的使用] 中的說(shuō)明雇初,將 Boost 頭文件目錄、Boost 庫(kù)文件目錄靖诗、Python 頭文件目錄、Python 靜態(tài)庫(kù)文件都導(dǎo)入到項(xiàng)目中支示。
- 選擇菜單“生成->生成 Project”,如果一切無(wú)誤颂鸿,將會(huì)生成一個(gè)
hello_ext.pyd
文件。由于生成器的默認(rèn)配置是Debug-x86
嘴纺,因此生成目錄為項(xiàng)目下的 Debug 目錄。 - 將
hello_ext.pyd
與hello.py
放在同一目錄下颖医,執(zhí)行hello.py
,將會(huì)看到輸出:hello, world
熔萧。