摘要:在實際開發過程當中,免不了涉及到混合編程,好比,對於python這種腳本語言,性能仍是有限的,在一些對性能要求高的情景下面,仍是須要使用c/c++來完成。
那怎樣作呢?咱們能使用pybind11做爲橋樑,pybind11的優勢是對C++ 11支持很好,API比較簡單,如今咱們就簡單記下Pybind11的入門操做。python
Pybind11 是一個輕量級只包含頭文件的庫,用於 Python 和 C++ 之間接口轉換,能夠爲現有的 C++ 代碼建立 Python 接口綁定。Pybind11 經過 C++ 編譯時的自省來推斷類型信息,來最大程度地減小傳統拓展 Python 模塊時繁雜的樣板代碼, 已經實現了 STL 數據結構、智能指針、類、函數重載、實例方法等到Python的轉換,其中函數能夠接收和返回自定義數據類型的值、指針或引用。linux
直接使用pip安裝 pip3 install pybind11 因爲pybind11依賴於pytest,因此在安裝前須要先把pytest給安裝上 pip3 install pytest
首先,咱們編寫一個C++源文件,命名爲example.cpp。ios
// pybind11 頭文件和命名空間 #include <pybind11/pybind11.h> namespace py = pybind11; int add(int i, int j) { return i + j; } PYBIND11_MODULE(example, m) { // 可選,說明這個模塊是作什麼的 m.doc() = "pybind11 example plugin"; //def( "給python調用方法名", &實際操做的函數, "函數功能說明" ). 其中函數功能說明爲可選 m.def("add", &add, "A function which adds two numbers", py::arg("i")=1, py::arg("j")=2); }
PYBIND11_MODULE()宏函數將會建立一個函數,在由Python發起import語句時該函數將會被調用。模塊名字「example」,由宏的第一個參數指定(千萬不能出現引號)。第二個參數"m",定義了一個py::module的變量。函數py::module::def()生成綁定代碼,將add()函數暴露給Python。c++
咱們使用CMake進行編譯。首先寫一個CMakeLists.txt。git
cmake_minimum_required(VERSION 2.8.12) project(example) add_subdirectory(pybind11) pybind11_add_module(example example.cpp)
就是CMakeList.txt和example.cpp放在一個目錄下面。github
cmake . make
會生成example.cpython-36m-x86_64-linux-gnu.so文件。算法
這個文件就是python能夠調用的文件。仍是在相同目錄下運行python,進入python命令行編程
import example example.add(3, 4) [out]: 7
在使用python編程時,常使用內建容器做爲函數的參數和返回值,python語言的這種特性使咱們的程序變得很是靈活和易於理解。那麼在使用pybind11封裝C++實現的函數的時候,如何保留這一特性呢?本文介紹pybind11實現list和dict做爲參數及返回值的方法。segmentfault
//文件名:func.cpp #include "func.h" vector<long> list_square(vector<long> &in_list, vector<long>& out_list){ vector<long>::iterator iter; for(iter = in_list.begin(); iter != in_list.end(); iter++){ out_list.push_back(*iter * *iter); } return out_list; } map<string, long> dict_square(map<string, long>& in_dict, map<string, long>& out_dict){ map<string, long>::iterator iter; iter = in_dict.begin(); while(iter != in_dict.end()){ out_dict.insert({iter->first, iter->second * iter->second}); iter++; } return out_dict; }
寫pybind11封裝函數數據結構
//文件名:func_wrapper.cpp #include <pybind11/pybind11.h> #include<pybind11/stl.h> #include "func.h" PYBIND11_MODULE(square, m){ m.doc() = "Square the members of the container"; m.def("list_square", &list_square); m.def("dict_square", &dict_square); }
#include <pybind11/pybind11.h> #include <iostream> struct Foo { std::string a; }; void show(Foo f) { std::cout << f.a << std::endl; } namespace py = pybind11; PYBIND11_PLUGIN(example) { py::module m("example", "pybind11 example plugin"); m.def("show", &show, "Prints a"); py::class_<Foo>(m, "Foo") .def_readwrite("a", &Foo::a); return m.ptr(); }
寫pybind11封裝函數
import sys sys.path.append(".") import example b = example.Foo b.a = "Hello" example.show(b)
此外:提供一些經常使用的參考連接
pybind11 — Seamless operability between C++11 and Python
python調用c++利器–pybind11
基於pybind11實現Python調用c++編寫的CV算法–下 (Linux+Cmake)
跟我一塊兒學習pybind11 之一
pybind11封裝的函數實現內建容器做爲參數及返回值
本文分享自華爲雲社區《混合編程 — python調用C++之pybind11入門》,原文做者:SNHer。