logo

Thursday 24th of May 2012

廣告

廣告贊助商

首頁 Python教學 Python進階教學 使用C++擴充Python
使用C++擴充Python PDF 列印 E-mail
作者是 Victor   
週三, 11 二月 2009 21:09

使用C++擴充Python

使用C++的Boost.Python括充一個Python的模組教學

為什麼要擴充Python?

時常有人問Python到底能做什麼,我的回答是,看你要拿Python來做什麼,因為Python可以用C語言擴充,這表示C語言能做到的事都可以由 Python,現有的函式庫如果辦不到,大不了你自己寫一個,這不僅僅是只有這樣的好處而已,很多時候我們希望能有Python的彈性、可讀性等各種好 處,但又有C語言的高效率,就可以將整個程式中較吃重的工作用C語言寫成module供Python使用,同時兼俱彈性與效率

使用的工具

我們要使用的是C++的Boost函式庫裡的Python模組,它是用來包裝C++供Python使用的函式庫,不使用這個函式庫的話,你必須使用Python提供的C語言API自行包裝,在這裡我們示範如何使用Boost.Python來包裝成模組讓Python使用

在開始之前,你必須確定你有安裝Boost的函式庫,如果沒有的話,請到Boost的官方網站自行下載並編譯或安裝,如果不知道怎麼編譯可以考慮下載事先編譯完成的版本

第一個簡單的例子

我們參考Boost官方網站的 文件,一個簡單的模組

hello.cpp

char const* greet()
{
   return "hello, world";
}

#include 

BOOST_PYTHON_MODULE(hello_ext)
{
    using namespace boost::python;
    def("greet", greet);
}

有了Boost.Python的幫忙,用C++擴充Python會是一件超級簡單的事,相較於這個例子,編譯看起來就麻煩得多了

進行編譯

Boost.Python的模組通常都使用bjam來編譯,什麼是bjam呢? 它是boost的一套編譯系統,你可以下載原始碼自行編譯,同樣的如果你不知道如何自行編譯的話,可以 下載事先編譯的版本,在這裡我們通常選ntx86,如果你用的是PC的話,然後確定你的bjam.exe的目錄在PATH的環境變數中,或著你可以直接把bjam.exe放在my_module.cpp的同一個資料夾下

 

接著我們必須建立bjam的編譯檔案,你可以在boost的目錄"\libs\python\example\quickstart"下面找到它們,複製到你的模組同樣的資料夾下並修改,分別是

boost-build.jam

# Copyright David Abrahams 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

# Edit this path to point at the tools/build/v2 subdirectory of your
# Boost installation.  Absolute paths work, too.
boost-build ../../../../tools/build/v2 ;

Jamroot

# Copyright David Abrahams 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

# Specify the path to the Boost project.  If you move this project,
# adjust the path to refer to the Boost root directory.
use-project boost 
  : ../../../.. ;

# Set up the project-wide requirements that everything uses the
# boost_python library defined in the project whose global ID is
# /boost/python.
project boost-python-quickstart
  : requirements <library>/boost/python//boost_python 
    ;

# Make the definition of the python-extension rule available
import python ;

# Declare a Python extension called hello.
python-extension extending : extending.cpp ;

# Declare an executable called embedding that embeds Python
exe embedding : embedding.cpp /python//python ;

import testing ;

# Declare a test of the extension module
testing.make-test run-pyd : extending test_extending.py : : test_ext ;

# Declare a test of the embedding application
testing.run embedding 
  :              # any ordinary arguments
  : script.py    # any arguments that should be treated as relative paths
  :              # requirements
  : test_embed ; # name of test

# Create a "test" target that runs all the tests
alias test : test_ext test_embed ;

# make sure the tests don't run by default
explicit test_ext test_embed test ;
;

兩個檔案,但是因為這些檔案的內容並不能直接使用,需要做一點修改,以下是我們修改的版本

boost-build.jam

# Copyright David Abrahams 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

# Edit this path to point at the tools/build/v2 subdirectory of your
# Boost installation.  Absolute paths work, too.
boost-build C:/boost/boost_1_35_0/tools/build/v2 ;

這個檔案我們修改了boost-build,設為絕對的路徑,你應該修改它成你安裝boost的位置

Jamroot

# Copyright David Abrahams 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

# Specify the path to the Boost project.  If you move this project,
# adjust the path to refer to the Boost root directory.
use-project boost 
  : I:/boost/boost_1_36_0 ;

# Set up the project-wide requirements that everything uses the
# boost_python library defined in the project whose global ID is
# /boost/python.
project boost-python-quickstart
  : requirements <library>/boost/python//boost_python 
  <threading>multi
;

# Make the definition of the python-extension rule available
import python ;

# Declare a Python extension called hello.
python-extension hello_ext : hello.cpp


我們修改了use-project boost的專案目錄位置,改成你放置my_module.cpp的地方,然後還有python-extension改成我們的模組名稱和.cpp檔位 置,除此之外我們還刪除了建置測試用的部份,以上兩個檔案都應放在和my_module.cpp同一個目錄下,準備完成就可以開始進行編譯,進入cmd, 切換目錄,執行bjam

cd c:\python_tutorial bjam

如果沒有錯誤,應該該會產生一個hello_ext.pyd的檔案,這時只要將它copy到Python的library目錄,或是你Python模組執行的目錄,除此之外還有boost相對應的python的DLL檔,就可以直接使用

import hello_ext
print hello_ext.greet()

像這樣就會印出hello, world的字樣,如果你不想使用shared的方式link到Boost.Python以及不想產生debug資訊,你可以選擇使用下列指令

bjam release link=static

更多的參數指令可以在這裡被找到

http://www.boost.org/doc/tools/build/doc/html/bbv2/advanced/invocation.html

如果你有需要增加include的目錄或是要link的lib,可以將project 的 requirements部份改寫

project boost-python-quickstart
  : requirements <library>/boost/python//boost_python
  <threading>multi
  <library>test.lib
  <include>header/util
;

詳細參數請參考

http://www.boost.org/doc/tools/build/doc/html/bbv2/advanced/builtins/features.html

常見錯誤

如果你在import時遇到下列錯誤

ImportError: dynamic module does not define init function (inithello)

那通常是你在BOOST_PYTHON_MODULE定義的名稱和在Jamroot定義的不同所引起的

最近更新在 週四, 12 二月 2009 01:38
 

核心是 Joomla!. Designed by: Free Joomla Theme, whois protect. Valid XHTML and CSS.