乐趣区

关于编程语言:混合编程如何用python11调用C

摘要: 在理论开发过程中,免不了波及到混合编程,比方,对于 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)

此外:提供一些罕用的参考链接

pybind11 — Seamless operability between C++11 and Python

python 调用 C ++ 之 pybind11 入门

python 调用 c ++ 利器–pybind11

基于 pybind11 实现 Python 调用 c ++ 编写的 CV 算法–下(Linux+Cmake)

跟我一起学习 pybind11 之一

Passing by value #161

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

本文分享自华为云社区《混合编程 — python 调用 C ++ 之 pybind11 入门》,原文作者:SNHer。

点击关注,第一工夫理解华为云陈腐技术~

退出移动版