This article is from huawei cloud community “mixed programming: how to call C++ with pybind11”, by SNHer.

In the actual development process, it is inevitable to involve mixed programming. For example, the performance of python scripting language is still limited, and in some high performance scenarios, it is still necessary to use C/C ++. So how do you do that? We can use pybind11 as a bridge. The advantage of pybind11 is that it supports C++ 11 very well and has a relatively simple API. Now let’s briefly write down how to get started with pybind11.

1. Introduction to Pybind11 and Environment Installation

Pybind11 is a lightweight header only library for interface conversions between Python and C++. You can create Python interface bindings for existing C++ code. Pybind11 uses C++ compile-time introspection to infer type information to minimize the cumbersome boilerboard code that traditionally extends Python modules. It has implemented Python transformations such as STL data structures, smart Pointers, classes, function overloading, instance methods, and so on. Where functions can receive and return values, Pointers, or references of custom data types.

Pip3 Install PyBind11 pip3 Install PyBind11 pip3 Install PyBind11 pip3 Install PyBind11 pip3 Install PyBind11 pip3 Install PyBind11 pip3 Install PyBind11Copy the code

2. Summing functions

First, we’ll write a C++ source file called example.cpp.

#include <pybind11/pybind11.h> namespace py = pybind11; int add(int i, int j) { return i + j; } PYBIND11_MODULE(example, m) {// Optional, specify what this module does. //def(" call method name to Python ", & actual function, "function description"). Ef ("add", &add, "A function which adds two numbers", py:: ARg (" I ")=1, py::arg("j")=2); }Copy the code

The PYBIND11_MODULE() macro creates a function that will be called when Python issues an import statement. The module name “example” is specified by the first argument to the macro (do not use quotation marks). The second argument, “m”, defines a variable py::module. The py::module::def() function generates binding code that exposes the add() function to Python.

We compile using CMake. First write a cmakelists.txt.

Cmake_minimum_required (VERSION 2.8.12) project(example) add_subdirectory(PyBind11) PyBind11_Add_module (example) example.cpp)Copy the code

Cmakelist. TXT and example. CPP in the same directory.

cmake .
make
Copy the code

The example.cpython-36m-x86_64-linux-gnu. So file is generated.

This is the file that Python can call. Run Python again in the same directory and go to the Python command line.

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

3. Mapping between STL and Python built-in data types

When programming in Python, we often use built-in containers as arguments and return values of functions. This feature of the Python language makes our programs very flexible and easy to understand. So how do you retain this feature when using pybind11 to encapsulate C++ implemented functions? This article describes how PyBind11 implements List and dict as arguments and return values.

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

Return to the vector

// File name: 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; }Copy the code
  • Write the PyBind11 wrapper function
// File name: 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); }Copy the code

Returns the 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();
}
Copy the code
  • Write the PyBind11 wrapper function
import sys
sys.path.append(".")
import example

b = example.Foo
b.a = "Hello"
example.show(b)
Copy the code

Click to follow, the first time to learn about Huawei cloud fresh technology ~