python使用Pybind11擴展c++的實現(xiàn)
Pybind11 是一個輕量級的C++ 庫,旨在無縫地將C++代碼綁定到Python。它簡化了C++ 函數(shù)、類和數(shù)據結構在Python中使用的過程,使得開發(fā)人員可以方便地在Python中調用C++ 代碼,同時保留兩者的性能優(yōu)勢下面將詳細介紹Pybind11的基本概念、安裝方法、用法以及示例代碼。
Pybind11的基本概念
Pybind11允許C++函數(shù)、類和其他對象暴露給Python,使得它們可以在Python中被直接調用。主要功能包括:
- 暴露C++函數(shù)和類給Python。
- 支持C++的STL容器和數(shù)據結構在Python中的使用。
- 支持C++的異常傳遞到Python。
- 允許使用Python對象和函數(shù)在C++中。
Pybind11 的優(yōu)點
- 兼容性強,支持 Python2.7、Python3.x、PyPy (PyPy2.7 >= 5.7);
- 可以在 C++ 中使用 lambda 表達式,并在 Python 中使用捕獲的變量;
- 大量使用移動特性,保證數(shù)據轉移時的性能;
- 可以很方便地通過 Python buffer protocol 進行數(shù)據類型的轉移;
- 可以很方便地對函數(shù)進行向量化加速;
- 支持使用 Python 的切片語法;
- Pybind11 是 header-only 的,只需要包含頭文件即可;
- 相比于 Boost::Python,生成的二進制文件體積更??;
- 函數(shù)簽名通過 constexper 提前計算,進一步減小二進制文件體積;
- C++ 中的類型可以很容易地進行序列化/反序列化;
Python 以其靈活和易于上手的特點,成為了當下炙手可熱的編程語言。然而,動態(tài)解釋型語言的特點限制了其性能。因此在需要性能的地方,往往使用 C、C++ 等傳統(tǒng)高性能語言實現(xiàn)(如 numpy 這種科學計算庫),并在 Python 中調用。這就是所謂的混合編程,發(fā)揮各自的優(yōu)勢,取長補短。
Pybind11出來以前,Python和C/C++混合編程
Python 的 C-API (Python.h)
SWIG
Python 的 ctypes 模塊
Cython
Boost::Python
安裝Pybind11
Pybind11可以通過pip輕松安裝:
pip install pybind11
或者可以從源碼安裝:
git clone https://github.com/pybind/pybind11.git cd pybind11 mkdir build cd build cmake .. make install
用法示例
1. 暴露簡單的C++函數(shù)
首先,創(chuàng)建一個簡單的C++函數(shù),然后使用Pybind11將其暴露給Python。
C++代碼(example.cpp):
#include <pybind11/pybind11.h>
// 簡單的C++函數(shù)
int add(int i, int j) {
return i + j;
}
// Pybind11模塊定義
PYBIND11_MODULE(example, m) {
m.def("add", &add, "A function which adds two numbers");
}
編譯上面的代碼:
c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
然后在Python中使用:
import example print(example.add(2, 3)) # 輸出: 5
2. 暴露C++類
Pybind11還可以暴露C++類,并在Python中創(chuàng)建和操作這些類的實例。
C++代碼(example.cpp):
#include <pybind11/pybind11.h>
class Pet {
public:
Pet(const std::string &name) : name(name) {}
void setName(const std::string &name_) { name = name_; }
std::string getName() const { return name; }
private:
std::string name;
}
PYBIND11_MODULE(example, m) {
pybind11::class_<Pet>(m, "Pet")
.def(pybind11::init<const std::string &>())
.def("setName", &Pet::setName)
.def("getName", &Pet::getName);
}
編譯代碼:
c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
在Python中使用:
import example
p = example.Pet("Mittens")
print(p.getName()) # 輸出: Mittens
p.setName("Whiskers")
print(p.getName()) # 輸出: Whiskers
更多功能
暴露STL容器
Pybind11可以將C++的STL容器(如std::vector、std::map等)暴露給Python。
C++代碼(example.cpp):
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <vector>
std::vector<int> get_vector() {
return {1, 2, 3, 4, 5};
}
PYBIND11_MODULE(example, m) {
m.def("get_vector", &get_vector);
}
編譯代碼:
c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
在Python中使用:
import example print(example.get_vector()) # 輸出: [1, 2, 3, 4, 5]
異常處理
Pybind11支持將C++中的異常傳遞到Python,并在Python中進行處理。
C++代碼(example.cpp):
#include <pybind11/pybind11.h>
void throws_exception() {
throw std::runtime_error("An error occurred!");
}
PYBIND11_MODULE(example, m) {
m.def("throws_exception", &throws_exception);
}
編譯代碼:
c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
在Python中使用:
import example
try:
example.throws_exception()
except RuntimeError as e:
print(e) # 輸出: An error occurred!
總結
Pybind11是一個強大且易于使用的工具,允許開發(fā)人員將C++ 代碼無縫地集成到Python項目中。通過Pybind11,可以高效地暴露C++ 函數(shù)、類和數(shù)據結構,并在Python中進行調用和操作。其支持STL容器、異常處理等特性,使得它在C++ 與Python交互中表現(xiàn)得非常出色。使用Pybind11,可以充分利用C++的性能優(yōu)勢,同時享受Python的開發(fā)便利性。
到此這篇關于python使用Pybind11擴展c++的實現(xiàn)的文章就介紹到這了,更多相關Pybind11擴展c++內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

