Skip to content

Instantly share code, notes, and snippets.

@AtomicVar
Created December 17, 2023 14:13
Show Gist options
  • Save AtomicVar/00f40874bc7368d2eb74b98247d44570 to your computer and use it in GitHub Desktop.
Save AtomicVar/00f40874bc7368d2eb74b98247d44570 to your computer and use it in GitHub Desktop.
Call Python from C++
/**
* @file main.cpp
* @brief 演示如何在 C++ 中将数据传递给 Python,然后在 Python 中用 NumPy 进行计算,最后将结果返回给
* C++。
* @author Guo Shuai (gs0801@foxmail.com)
*/
#include <pybind11/pybind11.h>
#include <pybind11/embed.h>
#include <pybind11/numpy.h>
#include <iostream>
#include <vector>
namespace py = pybind11;
int main() {
// 1. 创建一个能自动初始化和销毁的 Python 解释器(RAII 机制)。
py::scoped_interpreter guard{};
// 2. 在 C++ 的数据(std::vector),能通过 py::globals() 传递给 Python。
// - py::array_t<int> 相当于 Python 中的 numpy.array(int32 类型)。
// - py::globals() 相当于 Python 中的 globals() 函数,即一个记录全局作用域变量的 dict。
// - py::globals()["a"] 相当于 Python 中的 globals()["a"],即获取全局变量 a。
std::vector<int> v{1, 2, 3, 4};
py::array_t<int> a{static_cast<ssize_t>(v.size()),
v.data()}; // 调用参数为 (size, *data) 的构造函数。
py::globals()["a"] = a;
// 3. 执行 Python 代码。
// 这里可以看到我们直接使用了 a,没有创建它,因为 a 已经在上面 C++ 代码创建了。
py::exec(R"(
import numpy as np
b = 2 * np.sqrt(a)
print("Python result:", b)
)");
// 4. 从 py::globals() 这个 dict 中获取全局变量 b,并以 py::array_t<float> 类型返回。
py::array_t<float> b = py::globals()["b"].cast<py::array_t<float>>();
// 5. 在 C++ 中打印 b 的内容。
// - b.request() 返回一个 py::buffer_info 对象,包含了 b 的元信息(数据指针、形状、步长等)。
// - b.request().ptr 返回 void* 类型的数据指针。
std::cout << "C++ result: [";
float* data = static_cast<float*>(b.request().ptr);
for (int i = 0; i < b.size(); ++i) {
std::cout << data[i] << ", ";
}
std::cout << "]" << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment