日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

Boost.Python教程:通用技术

發(fā)布時(shí)間:2024/3/26 python 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Boost.Python教程:通用技术 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

下面介紹一些有用的技術(shù),您可以在使用Boost.Python包裝代碼時(shí)使用這些技術(shù)。

創(chuàng)建包

Python包是一組模塊,為用戶提供某種功能。?如果您不熟悉如何創(chuàng)建包,?Python教程中提供了對它們的一個(gè)很好的介紹。

但是我們使用Boost.Python包裝C ++代碼。?我們?nèi)绾螢橛脩籼峁┮粋€(gè)漂亮的包界面??為了更好地解釋一些概念,讓我們使用一個(gè)例子。

我們有一個(gè)有不同含義的C ++庫:讀取和寫入各種格式,對聲音數(shù)據(jù)應(yīng)用濾波器等。它被命名(方便)?sounds?。?我們的庫已經(jīng)有了一個(gè)簡潔的C ++命名空間層次結(jié)構(gòu),如下所示:

sounds::core sounds::io sounds::filters

我們想向Python用戶提供相同的層次結(jié)構(gòu),允許他編寫如下代碼:

import sounds.filters sounds.filters.echo(...) # echo is a C++ function

第一步是編寫包裝代碼。?我們必須使用Boost.Python單獨(dú)導(dǎo)出每個(gè)模塊,如下所示:

/* file core.cpp */ BOOST_PYTHON_MODULE(core) {/* export everything in the sounds::core namespace */... }/* file io.cpp */ BOOST_PYTHON_MODULE(io) {/* export everything in the sounds::io namespace */... }/* file filters.cpp */ BOOST_PYTHON_MODULE(filters) {/* export everything in the sounds::filters namespace */... }

編譯這些文件將生成以下Python擴(kuò)展:?core.pyd?,?io.pyd和io.pyd?。

注意

擴(kuò)展名.pyd用于python擴(kuò)展模塊,它們只是共享庫。?使用系統(tǒng)的默認(rèn)設(shè)置,例如Unix的.so和Windows的.dll?,也可以。

現(xiàn)在,我們?yōu)镻ython包創(chuàng)建這個(gè)目錄結(jié)構(gòu):

sounds/__init__.pycore.pydfilters.pydio.pyd

文件__init__.py告訴Python該目錄sounds/實(shí)際上是一個(gè)Python包。?它可以是一個(gè)空文件,但也可以執(zhí)行一些魔術(shù),稍后將會顯示。

現(xiàn)在我們的包準(zhǔn)備好了。?用戶所要做的就是將sounds放入他的PYTHONPATH并啟動解釋器:

>>> import sounds.io >>> import sounds.filters >>> sound = sounds.io.open('file.mp3') >>> new_sound = sounds.filters.echo(sound, 1.0)

很不錯吧?

這是創(chuàng)建包層次結(jié)構(gòu)的最簡單方法,但它不是很靈活。?如果我們想要將純?Python函數(shù)添加到過濾器包中,例如,一次在聲音對象中應(yīng)用3個(gè)過濾器,該怎么辦??當(dāng)然,您可以在C ++中執(zhí)行此操作并將其導(dǎo)出,但為什么不在Python中執(zhí)行此操作??您不必重新編譯擴(kuò)展模塊,而且編寫它會更容易。

如果我們想要這種靈活性,我們將不得不使我們的包層次結(jié)構(gòu)復(fù)雜化。?首先,我們將不得不更改擴(kuò)展模塊的名稱:

/* file core.cpp */ BOOST_PYTHON_MODULE(_core) {.../* export everything in the sounds::core namespace */ }

請注意,我們在模塊名稱中添加了下劃線。?文件名也必須更改為_core.pyd?,我們對其他擴(kuò)展模塊執(zhí)行相同的操作。?現(xiàn)在,我們改變我們的包層次結(jié)構(gòu)如下:

sounds/__init__.pycore/__init__.pycore.pydfilters/\_init__.pyfilters.pydio/\_init__.py_io.pyd

請注意,我們?yōu)槊總€(gè)擴(kuò)展模塊創(chuàng)建了一個(gè)目錄,并為每個(gè)擴(kuò)展模塊添加了__init__.py。?但是如果我們這樣離開,用戶將不得不使用以下語法訪問核心模塊中的函數(shù):

>>> import sounds.core._core >>> sounds.core._core.foo(...)

這不是我們想要的。?但是這里輸入__init__.py魔術(shù):用戶可以直接訪問帶到__init__.py命名空間的所有內(nèi)容。?因此,我們所要做的就是將整個(gè)命名空間從_core.pyd帶到core/__init__.py?。?所以將這行代碼添加到sounds/core/__init__.py?:

from _core import *

我們對其他包也這樣做。?現(xiàn)在,用戶像以前一樣訪問擴(kuò)展模塊中的函數(shù)和類:

>>> import sounds.filters >>> sounds.filters.echo(...)

另外一個(gè)好處是我們可以輕松地將純Python函數(shù)添加到任何模塊中,這樣用戶就無法區(qū)分C ++函數(shù)和Python函數(shù)。?讓我們將一個(gè)純?Python函數(shù)echo_noise添加到filters包中。?此函數(shù)在給定的sound對象中按順序應(yīng)用echo和noise濾波器。?我們創(chuàng)建一個(gè)名為sounds/filters/echo_noise.py的文件并編寫我們的函數(shù):

import _filters def echo_noise(sound):s = _filters.echo(sound)s = _filters.noise(sound)return s

接下來,我們將此行添加到sounds/filters/__init__.py?:

from echo_noise import echo_noise

就是這樣。?用戶現(xiàn)在可以像filters包中的任何其他功能一樣訪問此功能:

>>> import sounds.filters >>> sounds.filters.echo_noise(...)

在Python中擴(kuò)展包裝對象

由于Python的靈活性,您可以輕松地向類添加新方法,即使它已經(jīng)創(chuàng)建了:

>>> class C(object): pass >>> >>> # a regular function >>> def C_str(self): return 'A C instance!' >>> >>> # now we turn it in a member function >>> C.__str__ = C_str >>> >>> c = C() >>> print c A C instance! >>> C_str(c) A C instance!

是的,Python rox。?

我們可以對使用Boost.Python包裝的類執(zhí)行相同的操作。?假設(shè)我們在C ++中有一個(gè)類point?:

class point {...};BOOST_PYTHON_MODULE(_geom) {class_<point>("point")...; }

如果我們使用上一個(gè)會話創(chuàng)建包中的技術(shù)?,我們可以直接編碼到geom/__init__.py?:

from _geom import *# a regular function def point_str(self):return str((self.x, self.y))# now we turn it into a member function point.__str__ = point_str

從C ++創(chuàng)建的所有點(diǎn)實(shí)例也將具有此成員函數(shù)!?這種技術(shù)有幾個(gè)優(yōu)點(diǎn):

  • 對于這些附加功能,將編譯時(shí)間減少到零
  • 將內(nèi)存占用減少到幾乎為零
  • 最大限度地減少重新編譯的需要
  • 快速原型設(shè)計(jì)(如果需要,您可以將代碼移動到C ++而無需更改接口)

您甚至可以使用元類添加一點(diǎn)語法糖。?讓我們創(chuàng)建一個(gè)特殊的元類,在其他類中“注入”方法。

# The one Boost.Python uses for all wrapped classes. # You can use here any class exported by Boost instead of "point" BoostPythonMetaclass = point.__class__class injector(object):class __metaclass__(BoostPythonMetaclass):def __init__(self, name, bases, dict):for b in bases:if type(b) not in (self, type):for k,v in dict.items():setattr(b,k,v)return type.__init__(self, name, bases, dict)# inject some methods in the point foo class more_point(injector, point):def __repr__(self):return 'Point(x=%s, y=%s)' % (self.x, self.y)def foo(self):print 'foo!'

現(xiàn)在讓我們看看它是如何得到的:

>>> print point() Point(x=10, y=10) >>> point().foo() foo!

另一個(gè)有用的想法是用工廠函數(shù)替換構(gòu)造函數(shù):

_point = pointdef point(x=0, y=0):return _point(x, y)

在這個(gè)簡單的情況下,沒有太多的收獲,但對于具有許多重載和/或參數(shù)的構(gòu)造函數(shù),這通常是一個(gè)很大的簡化,同樣幾乎沒有內(nèi)存占用和關(guān)鍵字支持的零編譯時(shí)開銷。

縮短編譯時(shí)間

如果您曾經(jīng)導(dǎo)出過很多類,那么您知道編譯Boost.Python包裝器需要相當(dāng)長的時(shí)間。?此外,內(nèi)存消耗很容易變得太高。?如果這導(dǎo)致您出現(xiàn)問題,可以將class_ definitions拆分為多個(gè)文件:

/* file point.cpp */ #include <point.h> #include <boost/python.hpp>void export_point() {class_<point>("point")...; }/* file triangle.cpp */ #include <triangle.h> #include <boost/python.hpp>void export_triangle() {class_<triangle>("triangle")...; }

現(xiàn)在,您創(chuàng)建一個(gè)main.cpp文件,其中包含BOOST_PYTHON_MODULE宏,并調(diào)用其中的各種導(dǎo)出函數(shù)。

void export_point(); void export_triangle();BOOST_PYTHON_MODULE(_geom) {export_point();export_triangle(); }

編譯并鏈接所有這些文件會產(chǎn)生與通常方法相同的結(jié)果:

#include <boost/python.hpp> #include <point.h> #include <triangle.h>BOOST_PYTHON_MODULE(_geom) {class_<point>("point")...;class_<triangle>("triangle")...; }

但記憶得到了控制。

如果您正在開發(fā)C ++庫并同時(shí)將其導(dǎo)出到Python,也建議使用此方法:類中的更改只需要編譯單個(gè)cpp,而不是整個(gè)包裝器代碼。

注意

如果在編譯大型源文件時(shí)收到錯誤消息“致命錯誤C1204:編譯器限制:內(nèi)部結(jié)構(gòu)溢出”?,此方法也很有用,如FAQ中所述。

總結(jié)

以上是生活随笔為你收集整理的Boost.Python教程:通用技术的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。