pybind11以及打包學習

2021-10-07 17:24:57 字數 2799 閱讀 5763

最近在看fasttext,看到使用pybind11把c++**封裝了一下,然後打包後安裝,python可以直接呼叫,非常方便,有點興趣,手動試了簡單例子,本篇沒啥乾貨,簡單記錄下實現過程。

c/c++**都是用pybind11封裝,可以直接用pip安裝即可,官方給出的入門示例十分簡單:

#include int add(int i, int j) 

pybind11_module(example, m)

其中,add函式為c函式,也是需要匯出的函式功能。pybind11_module功能就是負責匯出模組,第乙個為巨集引數(不需要雙引號,setup.py中有引數對應),第二個引數就代表模組物件(py::module)。m.def負責定義需要匯出的函式。官網強調,pybind是標頭檔案依賴,即只需要指定標頭檔案即可,不需要其它類庫。

import python_example as m

assert m.__version__ == '0.0.1'

assert m.add(1, 2) == 3

assert m.subtract(1, 2) == -1

這裡說下示例,編譯的時候有一行會報語法錯誤:

m.attr("__version__") = version_info;
這裡應該是編譯器認為用double型別給字串賦值了,所以總是報錯,搜了一下轉字串的巨集:

#define str1(r)  #r

#define str2(r) str1(r)

然後呼叫str2轉換一下就行了。

打包主要借助setuptools提供的介面,需要的操作都在setup.py中定義,然後用pip安裝。還是拿python_example當例子:

ext_modules = [

extension(

'python_example',

# sort input source files to ensure bit-for-bit reproducible builds

sorted(['src/main.cpp']),

include_dirs=[

# path to pybind11 headers

get_pybind_include(),

],language='c++'

),]

這個就是定義需要匯出模組的一些資訊,包括模組巨集名,前面提到的pybind11_module的第乙個引數就是對應的extension的第乙個引數的名字,如果兩者不一致,會導致編譯錯誤;第二個引數定義了需要編譯的原始檔; include_dirs是依賴的標頭檔案;language指定源語言。

class buildext(build_ext):

"""a custom build extension for adding compiler-specific options."""

def build_extensions(self):

for ext in self.extensions:

ext.define_macros = [('version_info', '{}"'.format(self.distribution.get_version()))]

ext.extra_compile_args = opts

ext.extra_link_args = link_opts

build_ext.build_extensions(self)

這個就是自定義模組編譯地方,對於每個自定義的模組(即前面的ext_modules),在build_extensions函式中,可以對每個模組指定一些巨集定義(define_macros)、編譯引數(extra_compile_args)以及鏈結引數(extra_link_args)等, 用於模組編譯的需要。

而最後一部分setup物件:

setup(

name='python_example',

version=__version__,

author='sylvain corlay',

author_email='[email protected]',

url='',

description='a test project using pybind11',

long_description='',

ext_modules=ext_modules,

setup_requires=['pybind11>=2.5.0'],

cmdclass=,

zip_safe=false,

)

定義了模組的一些資訊,如模組名(import時使用),作者,版本號之類的,其中需要關注的是cmdclass引數,這裡指定了模組編譯需要使用的類。整個setup.py核心內容就這些,是不是感覺也不複雜?

對了,有的同學可能會問,c/c++編譯器好像沒指定哦?是的,這個交給setuptools去幹了,官網介紹是setuptools會找到當初安裝python的那套環境去編譯這些模組,也就是既然python都裝上了,預設你的機器上編譯環境應該是可以編譯這些自定義模組的。

總體來說,使用起來感覺挺方便的。但是對我來講,最起碼暴露了乙個問題,c/c++好久沒用了,上面那個示例編譯錯誤,搞挺久才搞定,技藝生疏了。另外,更底層的流程,還是一竅不通,比如,python函式呼叫是怎麼呼叫到c/c++庫中去的,模組到底是怎麼定義的(我沒找到編譯出來的庫檔案),有時間再繼續扒吧。

pybind11原始碼

pybind11官方文件

python_example原始碼

python呼叫c 介面 pybind11

pybind11是乙個將c 介面轉接給python的庫,它支援c 11標準的編譯器。這裡我做了乙個簡單的實驗,主要是驗證將eigen matrixxf型別對映到numpy ndarray型別,這樣就可以在python愉快地呼叫c 函式了。完整 見 首先,python指令碼 usr bin env p...

pybind11使用教程筆記 4 2

當 include,std vector std deque std list std array std set std unordered set and std map std unordered map 和python list,set and dict data structures會自動...

pybind11 工具轉換 C 介面

pybind11 是乙個輕量級的 header only 庫,可以將 c 型別暴露給 python,反之亦然,主要用來將 c 介面轉成 python。apt install python3 devgit clone git submodule update init recursive cmakel...