首页 > 编程语言 >混合编程:如何用pybind11调用C++

混合编程:如何用pybind11调用C++

时间:2022-08-25 19:57:49浏览次数:136  
标签:python 编程 list iter dict C++ pybind11 example

摘要:在实际开发过程中,免不了涉及到混合编程,比如,对于python这种脚本语言,性能还是有限的,在一些对性能要求高的情景下面,还是需要使用c/c++来完成。

本文分享自华为云社区《混合编程:如何用pybind11调用C++》,作者:SNHer。

在实际开发过程中,免不了涉及到混合编程,比如,对于python这种脚本语言,性能还是有限的,在一些对性能要求高的情景下面,还是需要使用c/c++来完成。那怎样做呢?我们能使用pybind11作为桥梁,pybind11的优点是对C++ 11支持很好,API比较简单,现在我们就简单记下Pybind11的入门操作。

1.pybind11简介与环境安装

Pybind11 是一个轻量级只包含头文件的库,用于 Python 和 C++ 之间接口转换,可以为现有的 C++ 代码创建 Python 接口绑定。Pybind11 通过 C++ 编译时的自省来推断类型信息,来最大程度地减少传统拓展 Python 模块时繁杂的样板代码, 已经实现了 STL 数据结构、智能指针、类、函数重载、实例方法等到Python的转换,其中函数可以接收和返回自定义数据类型的值、指针或引用。

复制代码
直接使用pip安装

pip3 install pybind11

由于pybind11依赖于pytest,所以在安装前需要先把pytest给安装上

pip3 install pytest
复制代码

2. 求和函数

首先,我们编写一个C++源文件,命名为example.cpp。

复制代码
// 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。

我们使用CMake进行编译。首先写一个CMakeLists.txt。

cmake_minimum_required(VERSION 2.8.12)
project(example)

add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)

就是CMakeList.txt和example.cpp放在一个目录下面。

cmake .
make

会生成example.cpython-36m-x86_64-linux-gnu.so文件。

这个文件就是python可以调用的文件。还是在相同目录下运行python,进入python命令行

import example
example.add(3, 4)
[out]: 7

3. STL和python内建数据类型的对应关系

在使用python编程时,常使用内建容器作为函数的参数和返回值,python语言的这种特性使我们的程序变得非常灵活和易于理解。那么在使用pybind11封装C++实现的函数的时候,如何保留这一特性呢?本文介绍pybind11实现list和dict作为参数及返回值的方法。

返回vector

复制代码
//文件名: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);  
}
复制代码

返回struct

复制代码
#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)
复制代码

标签:python,编程,list,iter,dict,C++,pybind11,example
From: https://www.cnblogs.com/lidabo/p/16625506.html

相关文章

  • 【Java高级编程】IO流学习笔记
    目录IO流File类文件/文件夹基础操作创建文件的完整步骤IO流-节点流读入文件一个字节(一个字节)[FileInputStream]字节数组的方式读取(读取全部内容)[FileInputStream]读取......
  • pybind11使用记录---ubuntu下使用cmake编译c++工程为python库
    前言:因为最近c++下的工程需要在python下调用,所以需要把c++编译成可供python调用的库,记录一下具体做法:编译c++有多种方法,因为我的是cmake构建的工程,所以直接在cmake的......
  • mac上sublime的配置,支持c++11且支持输入
    支持c++11且可从终端输入在sublime下打开tools然后newbuildsystem,在出来的文件中写入如下:{"cmd":["bash","-c","g++'${file}'-std=c++11-stdlib=libc++......
  • C++类型转换
    const_cast一般用于去除const属性,将常量转变为非常量 dynamic_cast一般用于多态转换,有运行时安全检测 static_cast对比dynamic_cast没有运行时安全检测非同一继......
  • 阅读《计算机图形学编程(使用OpenGL和C++)》8 - 纹理贴图
    纹理贴图就是将图片贴到模型上,让模型看起来更真实。纹理贴图非常重要,因此硬件也为它提供了支持,使得它具备了实现实时的照片级真实感的超高性能。纹理单元是专为纹理设计的......
  • Linux编程:信号
    1.信号概念信号是软件中断,很多比较重要的应用程序都需要信号处理。信号是一种进程之间或者内核与进程间异步通信的一种机制,例如:用户在终端键入中断键,会通过信号机制停......
  • C++中map,multimap和unordered_map的区别
    map、multimap容器map的所有元素都是pair,同时拥有键值(key)和实值(value)pair的第一元素被视为键值,第二元素被视为实值性质:以rb_tree为底层结构,因此元素有自动排序的特性,......
  • C++学习笔记《面向对象概述》
    《面向对象概述》1.面向过程的结构化编程:把数据和动作分开放置,把数据放入到动作当中。采用自顶向下的方法构建程序,包含顺序,选择和循环三种结构。按照程序执行的时序步骤来......
  • 基于opencv的RTSP(rtsp)流读取和保存(C++可cmake编译-附带py方法)
     因其工作需要使用C++读取rtsp流,本文将针对linux下c++版读取视频流保存视频,凌乱且各种错误。现将将其成功执行的流程和代码记录,顺带也写了一份python读取rtsp方法,供自己......
  • Java函数式编程
    函数式编程-Stream流1.概述1.1为什么学?能够看懂公司里的代码大数量下处理集合效率高代码可读性高消灭嵌套地狱//查询未成年作家的评分在70以上的书籍由于洋流......