c++通過pybind11製作模型python接口,生成python調用包

我是在ubuntu系統進行實驗的,所以和window可能會有區別。

python調用C/C++有不少的方法,如boost.python, swig, ctypes, pybind11等,這些方法有繁有簡,而pybind11的優點是對C++ 11支持很好,API比較簡單,現在我們就簡單記下Pybind11的入門操作。

1. pybind11簡介與環境安裝

pybind11是一個輕量級的只包含頭文件的庫,它主要是用來在已有的 C++代碼的基礎上做擴展,它的語法和目標非常像Boost.Python,但Boost.Python爲了兼容現有的基本所有的C++編譯器而變得非常複雜和龐大,而因此付出的代價是很多晦澀的模板技巧以及很多不必要的對舊版編譯器的支持。Pybind11摒棄了這些支持,它只支持python2.7以上以及C++ 11以上的編譯器,使得它比Boost.Python更加簡潔高效。
爲了使用pybind11,我們需要支持C++ 11標準的編譯器(GCC 4.8以上,VS 2015 Update 3以上)以及python 2.7以上的版本,還需要下載CMake,有了這些以後,

cmake教程可以參考:https://blog.csdn.net/luanpeng825485697/article/details/81202136

  1. 首先,我們從 pybind11 github網址:https://github.com/pybind/pybind11 上下載源碼。
  2. cmake工程之前,要先安裝pytest pip install pytest,否則會出錯
  3. 用CMake編譯並運行測試用例:
進入pybind11的目錄,
cd tests
cmake ..
cmake --build . --config Release --target check

如果所有測試用例都通過了,說明安裝成功了。

2. python調用C++

下載編譯好pybind11之後,我們就可以開始對着官方的pybind11 Tutorial進行學習了,詳細的入門教程及語法請參考官方文檔,這裏,我們簡單演示下如何編寫供python調用的C++模塊.
首先,我們編寫一個C++源文件,命名爲example.cpp

#include <pybind11/pybind11.h>
namespace py = pybind11;

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

PYBIND11_MODULE(example, m)
{
    // optional module docstring
    m.doc() = "pybind11 example plugin";
    // expose add function, and add keyword arguments and default arguments
    m.def("add", &add, "A function which adds two numbers", py::arg("i")=1, py::arg("j")=2);

    // exporting variables
    m.attr("the_answer") = 42;
    py::object world = py::cast("World");
    m.attr("what") = world;
}

2.1 使用window編譯

我沒有實驗,所以可以參考別的教程

2.2 CMake的編譯方法

當然,我們也可以使用CMake進行編譯。首先寫一個CMakeLists.txt

cmake_minimum_required(VERSION 2.8.12)
project(example)   

add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)

這裏要求example.cpp放在和pybind11同一級的目錄下,因爲我們在CMakeLists.txt中調用了同目錄pybind11和同目錄的example.cpp文件。在當前目錄下執行

cmake .
make

會生成example.cpython-36m-x86_64-linux-gnu.so文件。這個文件就是python可以調用的文件。還是在相同目錄下運行python,進入python命令行

import example
example.add(3, 4)

[out]: 7

3、中級調用

上面是一個簡單的例子,有時我們需要的功能可能很複雜。

生成模型設計庫調用問題。

比如你的cpp文件中引用了其他的第三方庫,這個時候我們生成的so文件,可能是需要依賴第三方庫的。

本地myopencv.cpp文件

#include <pybind11/pybind11.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <string>

namespace py = pybind11;

void read_img(std::string img_path)
{
    cv::Mat image = cv::imread(img_path, CV_LOAD_IMAGE_COLOR);
}

PYBIND11_MODULE(myopencv, m)
{
    m.def("read_img", &read_img, "get image size");
}

CMakeLists.txt可以寫成下面這樣

cmake_minimum_required(VERSION 2.8.12)
project(myopencv)

add_subdirectory(pybind11)
pybind11_add_module(myopencv myopencv.cpp)

通過cmkae編譯通過

cmake .
make

產生myopencv.cpython-36m-x86_64-linux-gnu.so文件
在python中調用

import myopencv

目前這裏發現有問題,還沒有調通。。。。。

數據類型不匹配的問題

比如opencv在python中是numpy的類型,但是在c++中cv.Mat的類型

對於opencv的類型不匹配問題,github上已經給出瞭解決方法,

cpp和h文件下載地址 https://github.com/edmBernard/pybind11_opencv_numpy

如何你需要什麼可以去github上搜索,或者自己去實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章