【軟體開發】Pybind11教學:使用Pybind11實現Python和C++之間的互操作性

Pybind11是一個用於將C++代碼綁定到Python解析器的package。使用Pybind11可以方便地將現有的C++ Library或程式碼轉換為Python模塊,並在Python中使用。本文將介紹Pybind11的基本使用方法,包括如何安裝和使用Pybind11,以及如何編譯和使用C++代碼。

Pybind11

Pybind11安裝

要使用Pybind11,需要先安裝Python和C++編譯器。此外,還需要安裝pybind11庫。我認為最簡單的安裝方法是使用pip安裝pybind11:

pip install pybind11

也有其他安裝方法可以參考Pybind11網頁。在安裝了pybind11之後,就可以開始使用Pybind11。

編譯和使用C++代碼

使用setup.py編譯

編譯Pybind11的C++程式使其可以在Python中使用,需要完成以下步驟:

1. 編寫C++代碼

編寫需要綁定到Python的C++代碼。需要使用Pybind11的API來定義Python模塊和函數,例如:

#include <pybind11/pybind11.h>

int add(int i, int j) {
    return i + j;
}

PYBIND11_MODULE(example, m) {
    m.def("add", &add, "A function which adds two numbers");
}

在這個程式中,我們定義了一個名為add的函數,並使用PYBIND11_MODULE宏定義了一個名為example的Python模塊,並將add函數綁定到這個模塊中。

2. 編寫setup.py文件

創建一個名為setup.py的Python腳本,用於編譯Python模塊。這個腳本需要定義一個名為example的Extension對象,並將其傳遞給setup函數。

from setuptools import setup, Extension

module = Extension('example', sources=['example.cpp'])

setup(
    name='example',
    version='1.0',
    ext_modules=[module],
)

在這個Python程式中,我們定義了一個名為module的Extension對象,將example.cpp作為源文件,並將這個對象傳遞給setup函數。

3. 編譯Python模塊

利用以下指令來編譯此Python模塊。這將編譯C++程式碼並將其轉換為Python模塊。編譯成功後,可以在當前目錄下找到一個名為example.so或是example.cpython-38-x86_64-linux-gnu.so的檔案(Shared Library)。

python setup.py build_ext --inplace

4. 在Python中使用此Python模塊

現在,可以在Python中使用這個模塊了。以下是一個Python程式,使用這個模塊計算兩個數的和:

import example

print(example.add(1, 2))

透過這些步驟,我們可以編譯一個使用Pybind11庫綁定的C++程式,並將其轉換為Python模塊,從而在Python中使用。需要注意的是,每次更改C++程式碼之後,需要重新編譯Python模塊才能生效。

使用CMake編譯

除了使用setup.py腳本編譯Python模塊,還可以使用CMake來編譯Python模塊。以下是使用CMake編譯Python模塊的步驟:

1. 創建CMakeLists.txt文件

創建一個名為CMakeLists.txt的文件,包含以下範例內容:

cmake_minimum_required(VERSION 3.0)
project(pybind11_example)

# Find Python
find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})

# Find Pybind11
find_package(pybind11 REQUIRED)

# Add the example module
pybind11_add_module(example example.cpp)

# Link the module with Python
target_link_libraries(example PRIVATE ${PYTHON_LIBRARIES})

在這個CMakeLists.txt文件中,我們使用find_package來查找Python和Pybind11 packages,然後創建一個名為example的Python模塊,將example.cpp作為源文件。我們還需要使用target_link_libraries命令將Python和Pybind11庫連接到這個模塊中。

2. 創建build文件夾

創建一個名為build的文件夾,在這個文件夾中進行編譯。

mkdir build
cd build

3. 編譯Python模塊

在build文件夾中輸入以下command利用CMakeLists.txt文件中的代碼編譯Python模塊。在build資料夾中產生出example.so或example.cpython-38-x86_64-linux-gnu.so。

cmake .. && make

4. 在Python中使用Python模塊

現在,可以在Python中使用這個模塊了。以下是一個Python程式,將此程式與上述產生的example.so檔案放在同一個資料夾底下,即可使用這個模塊計算兩個數的和:

import example

print(example.add(1, 2))

如果要把產生的Shared Library放在其他目錄底下來使用,則需在此Python程式中使用sys.path.append函數添加模塊搜索路徑。例如:

import sys
sys.path.append('/path/to/example.so/dir')
import example

result = example.add(1, 2)
print(result)

使用C++編譯器進行編譯

如果既不想寫setup.py也不想寫CMakeLists.txt,也可以使用C++的Compiler直接編譯產生出相對應的Python package。這可能是一個較簡潔的方式。隨著不同的使用情境可以利用不同的方式來編譯example.so。

c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)

Pybind11其他功能

除了上面介紹的功能外,Pybind11還提供了許多其他功能。以下是一些常用的功能:

  • 支持Python對象和C++對象之間的轉換。可以在C++中使用pybind11::object類型來處理Python對象。
  • 支持Python的內建數據類型和標準庫數據類型與C++數據類型之間的轉換。例如,可以將Python列表轉換為C++向量,將Python字典轉換為C++映射等。
  • 支持使用C++11特性,例如lambda表達式和自動類型推斷。
  • 支持在Python中使用C++模板。
  • 支持使用C++庫,例如Eigen和OpenCV等。
  • 支持使用多線程,可以在C++代碼中使用C++11的低級線程庫或使用Python的低級線程庫。

Pybind11跟Boost.Python的比較

Pybind11和Boost.Python都是用於將C++代碼綁定到Python的Library。以下是它們之間的一些比較:

  1. 簡化程度:Pybind11相對於Boost.Python更為簡化,使用Pybind11可以更快速地將C++代碼綁定到Python,並且更容易學習和使用。Pybind11具有更簡潔的API,而Boost.Python則具有更多的庫功能和複雜性,需要較多的代碼來完成同樣的任務。
  2. 效率:由於Pybind11在底層使用了現代C++的一些特性,它比Boost.Python具有更高的性能和更低的開銷,因此在一些需要高效性能的場景中,Pybind11是更好的選擇。
  3. 兼容性:Boost.Python已經存在很長時間,因此它可以與許多較早版本的Python和C++庫兼容。Pybind11的兼容性也很好,但可能不如Boost.Python。
  4. 文件和社區支持:Boost.Python具有非常完整的文檔和社區支持,其中包括大量的教程和示例代碼。Pybind11的文檔和社區支持也很好,但可能不如Boost.Python。

總體而言,Pybind11和Boost.Python都是優秀的庫,都可以實現將C++代碼綁定到Python。使用哪個庫取決於開發人員的需求和使用情況。如果需要更高的性能和更簡化的庫,可以選擇Pybind11;如果需要更兼容的Library和完整的Community支持,可以選擇Boost.Python。然而,由於Pybind11的簡潔API和高效性能,現在越來越多的開發人員選擇Pybind11來實現Python和C++之間的互操作性。

總結

本文介紹了Pybind11的基本使用方法,包括如何安裝和使用Pybind11,以及如何編譯和使用C++代碼。通過使用Pybind11,開發人員可以方便地將現有的C++代碼轉換為Python模塊,並在Python中使用。Pybind11還提供了許多其他功能,例如支持Python對象和C++對象之間的轉換,支持使用C++ Library,支持使用多線程等。使用Pybind11,開發人員可以更輕鬆地將C++代碼與Python集成,並從兩種語言的優點中受益。

X. Ryan
X. Ryan

Hello!我是一個在矽谷工作,有軟體工程背景的量子計算科學家。這裡分享的內容主要是把平常研究開發時所用的小工具以及看過的東西記錄下來,同時也分享一些日常生活瑣事。

文章: 45