Apple iPhone 11 (A2223) 128GB 黑色 移动联通电信4G手机 双卡双待
4999元包邮
去购买 >
在使用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
{
values.push_back(j);
}
return values;
}
更好的方法:
vector fun1(int num, vector& values)
{
for(int j=0;j
{
values.push_back(j);
}
return values;
}
三.实现步骤
在头文件中声明函数;
用C++编写两个函数,list_square将输入的vector中的每个数字求平方,返回新的vector;dict_square将输入的map中的所有值求平方,返回新的map;
写pybind11封装函数;
用python编写setup脚本;
编译生成动态链接库;
测试函数功能。
四.代码实现
在头文件中声明函数
//文件名: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}