美文网首页Cython
pybind11快速实现c,c++ 与 python互通

pybind11快速实现c,c++ 与 python互通

作者: python测试开发 | 来源:发表于2022-01-28 10:36 被阅读0次

    简介

    pybind11是一个轻量级的头文件库, 为Python和C、C++实现了类型互通,主要用于为现有C++代码创建Python绑定。它的目标和语法与Boost.Python库相似:通过使用编译时自省来推断类型信息,最大限度地减少传统扩展模块中的模板代码。

    Boost是一个庞大而复杂的实用程序库套件,几乎可以与现存的所有C++编译器一起使用。这种兼容性是有代价的:为了支持最古老和最有问题的编译器,必须使用神秘的模板技巧和变通方法。现在与C++11兼容的编译器已经广泛使用,Boost已经包含过于庞大和不必要的依赖。

    pybind11是Boost.Python的精简版本,剥离了所有与绑定生成无关的东西。在没有注释的情况下,核心头文件只需要大约4K行代码,并且依赖于Python(2.7或3.5+,或PyPy)和C++标准库。这种紧凑的实现是由于一些新的C++11语言特性(特别是:tuple、lambda函数和变量模板)而实现的。

    教程和参考文档在https://pybind11.readthedocs.io/en/latest/提供。源代码可以在https://github.com/pybind/pybind11/获得。

    核心功能

    以下核心C ++功能可以映射到Python

    • 函数入参和返回值可以是自定义数据结构的值、引用或者指针
    • 实例方法和静态方法
    • 重载
    • 实例属性和静态属性
    • 任意异常类型
    • 枚举
    • 回调
    • 迭代器和range
    • 自定义操作符
    • 单继承和多继承
    • STL数据结构
    • 带有引用计数的智能指针,类似于std::shared_ptr
    • 正确的引用计数的内部引用
    • 带有虚函数和纯虚函数的C ++类可以在Python中扩展

    其他有用功能

    • Python 2.7,3.5+和PyPy/PyPy3 7.3支持与实现无关接口。
    • 将C++11 lambda函数与捕获的变量绑定在一起。lambda捕获的数据存储在生成的Python函数对象中。
    • pybind11使用C++11 move constructors 和 move assignment operators从而有效地转换自定义数据类型。
    • 通过Python的buffer协议,可以很容易地公开内部存储的自定义数据类型,比如C++矩阵类型如Eigen和NumPy之间进行快速转换。
    • pybind11可以自动将函数矢量化,以便它们透明地应用于以NumPy数组为参数的所有条目。
    • 只需几行代码就可以支持Python的基于切片的访问和赋值操作。
    • 一切都只包含在几个头文件中,没有必要链接任何其他库。
    • 与Boost.Python比二级制文件更小,编译时间更短,5倍速以上。
    • 函数签名是在编译时预先计算的(使用constexpr),生成更小的二进制文件。
    • 只需很少的额外工作,C ++类型就可以像Python对象一样进行pickled和unpickled。

    快速入门

    • 安装

    调试环境:ubuntu 20.04.3 LTS

    # pip install pybind11
    # git clone https://github.com/pybind/pybind11
    # cd pybind11/include
    

    创建文件example.cpp

    #include <pybind11/pybind11.h>
    
    int add(int i, int j) {
        return i + j;
    }
    
    PYBIND11_MODULE(example, m) {
        m.doc() = "pybind11 example plugin"; // optional module docstring
    
        m.def("add", &add, "A function that adds two numbers");
    }
    

    编译执行

    #  c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
    # ls
    example.cpp  example.cpython-38-x86_64-linux-gnu.so  pybind11
    # python
    Python 3.8.8 (default, Apr 13 2021, 19:58:26) 
    [GCC 7.3.0] :: Anaconda, Inc. on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import example
    >>> example.add(1, 2)
    3
    

    在c++中调用python

    demo.cpp

    #include <iostream>
    #include <pybind11/embed.h>
    
    namespace py = pybind11;
    using namespace std;
    
    int main()
    {
        cout << "Hello PyBind World" << endl;
    
        // start the interpreter and keep it alive
        py::scoped_interpreter guard{}; 
        py::module math = py::module::import("math");
        py::object result = math.attr("sqrt")(25);
        std::cout << "Sqrt of 25 is: " << result.cast<float>() << std::endl;
    }
    

    新建CMakeLists.txt

    project(pybind_demo)
    cmake_minimum_required(VERSION 3.13)
    set(CMAKE_CXX_STANDARD 14)  
    
    include(FetchContent)
    FetchContent_Declare(
        pybind11
        GIT_REPOSITORY https://github.com/pybind/pybind11.git
        GIT_TAG        v2.6.2
        GIT_SHALLOW    TRUE
    )
    
    FetchContent_MakeAvailable(pybind11)
    
    add_executable(demo demo.cpp)
    target_link_libraries(demo PRIVATE pybind11::embed)
    

    编译执行:

    $ cmake .
    CMake Warning (dev) at CMakeLists.txt:1 (project):
      Policy CMP0048 is not set: project() command manages VERSION variables.
      Run "cmake --help-policy CMP0048" for policy details.  Use the cmake_policy
      command to set the policy and suppress this warning.
    
      The following variable(s) would be set to empty:
    
        CMAKE_PROJECT_VERSION
        CMAKE_PROJECT_VERSION_MAJOR
        CMAKE_PROJECT_VERSION_MINOR
        CMAKE_PROJECT_VERSION_PATCH
    This warning is for project developers.  Use -Wno-dev to suppress it.
    
    -- pybind11 v2.6.2 
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /home/andrew/code/pybind11/include
    $ make
    Scanning dependencies of target demo
    [ 50%] Building CXX object CMakeFiles/demo.dir/demo.cpp.o
    [100%] Linking CXX executable demo
    [100%] Built target demo
    $ ./demo 
    Hello PyBind World
    Sqrt of 25 is: 5
    
    

    以上步骤需要保证对github的访问。参考资料:https://blog.devgenius.io/calling-python-and-c-code-using-pybind-99ab7fefa685

    在python中调用c++

    example.cpp

    #include <pybind11/embed.h>
    
    int multiply(int i, int j) {
        return i * j;
    }
    
    PYBIND11_MODULE(example, m) {
        m.doc() = "pybind11 example plugin"; // optional module docstring
        m.def("multiply", &multiply, "A function which multiplies two numbers");
    }
    

    新建CMakeLists.txt

    cmake_minimum_required(VERSION 3.13)
    project(pybind_demo)
    set(CMAKE_CXX_STANDARD 14)  
    
    include(FetchContent)
    FetchContent_Declare(
        pybind11
        GIT_REPOSITORY https://github.com/pybind/pybind11.git
        GIT_TAG        v2.6.2
        GIT_SHALLOW    TRUE
    )
    
    FetchContent_MakeAvailable(pybind11)
    
    pybind11_add_module(example example.cpp)
    target_compile_features(example PUBLIC cxx_std_14)
    set_target_properties(example PROPERTIES SUFFIX ".so")
    

    编译执行:

    $ cmake .
    -- pybind11 v2.6.2 
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /home/andrew/code/pybind11/include/exmaple
    $ make
    Scanning dependencies of target example
    [ 50%] Building CXX object CMakeFiles/example.dir/example.cpp.o
    [100%] Linking CXX shared module example.so
    [100%] Built target example
    $ ls
    CMakeCache.txt  CMakeFiles  cmake_install.cmake  CMakeLists.txt  _deps  example.cpp  example.so  Makefile
    $ python
    Python 3.8.8 (default, Apr 13 2021, 19:58:26) 
    [GCC 7.3.0] :: Anaconda, Inc. on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import example
    >>> example.multiply(3, 2)
    6
    

    相关文章

      网友评论

        本文标题:pybind11快速实现c,c++ 与 python互通

        本文链接:https://www.haomeiwen.com/subject/dlizhrtx.html