pybind11封装的函数实现内建容器作为参数及返回值

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

一.C++ STL和python内建数据类型的对应关系

C++ STL Python
std::vector list
std::array list
std::map dict
std::set set

二.应注意的问题

为了使C++函数能够返回vector对象,一般把要返回的vector容器放在函数的参数中,下面的两种方法在某些情况下可以达到相同的效果,但是建议使用第二种方法。因为如果使用前一种方法,且vector中存放的是类的对象,则函数返回时调用相关的类的析构函数。所以如果vector是一个局部的变量,那么返回该vector的引用是十分危险的,因为该vector已经被析构。返回map对象同理。

vector  fun1(int num)   
{   
    vector  values;   
    for(int j=0;j 

更好的方法:

vector  fun1(int num, vector& values)   
{     
    for(int j=0;j 

三.实现步骤

  1. 在头文件中声明函数;
  2. 用C++编写两个函数,list_square将输入的vector中的每个数字求平方,返回新的vector;dict_square将输入的map中的所有值求平方,返回新的map;
  3. 写pybind11封装函数;
  4. 用python编写setup脚本;
  5. 编译生成动态链接库;
  6. 测试函数功能。

四.代码实现

  • 在头文件中声明函数
//文件名:func.h  
#include   
#include   
#include   
  
using namespace std;  
  
vector list_square(vector&, vector&);  
map dict_square(map&, map&);
  • 用C++编写两个函数
//文件名:func.cpp  
#include "func.h"  
  
vector list_square(vector &in_list, vector& out_list){  
    vector::iterator iter;  
    for(iter = in_list.begin(); iter != in_list.end(); iter++){  
        out_list.push_back(*iter * *iter);  
    }  
    return out_list;  
}  
  
map dict_square(map& in_dict, map& out_dict){  
    map::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   
#include  
#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);  
}
  • 用python编写setup脚本
#文件名:setup.py  
from setuptools import setup, Extension  
  
functions_module = Extension(  
    name = 'square',  
    sources = ['func.cpp', 'func_wrapper.cpp'],  
    include_dirs = [r'D:\software\pybind11-master\include', 
                    r'D:\software\Anaconda\include']  
)  
  
setup(ext_modules = [functions_module])
  • 编译生成动态链接库

在命令行执行python setup.py build_ext --inplace,在当前路径下生成pyd动态库。

  • 测试函数功能
#文件名:test.py  
import square  
  
in_list = [30, 40, 50]  
out_list = list()  
out_list = square.list_square(in_list, out_list)  
print(out_list)  
  
print("-"*45)  
  
in_dict = {"小明": 30, "小红": 40, "小华": 50}  
out_dict = dict()  
out_dict = square.dict_square(in_dict, out_dict)  
print(out_dict)

output:
[900, 1600, 2500]
---------------------------------------------
{'小华': 2500, '小明': 900, '小红': 1600}

你可能感兴趣的:(python,c++)