【问题标题】:How to pass a vector by reference in pybind11 & c++如何在 pybind11 和 c++ 中通过引用传递向量
【发布时间】:2021-12-28 21:30:36
【问题描述】:

我尝试通过 pybind11 从 python 的引用将向量/数组传递给 C++ 库。 C++ 库可以填充数据。调用C++后,希望python端能拿到数据。

这是简化的 C++ 代码:

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>

class Setup
{
public:
    Setup(int version) : _version(version) {}
    int _version;
};

class Calculator
{
public:
    Calculator() {}
    static void calc(const Setup& setup, std::vector<double>& results) { ... }
}

namespace py = pybind11;

PYBIND11_MODULE(one_calculator, m) {
    // optional module docstring
    m.doc() = "pybind11 one_calculator plugin";

    py::class_<Setup>(m, "Setup")
        .def(py::init<int>());

    py::class_<Calculator>(m, "Calculator")
        .def(py::init<>())
        .def("calc", &Calculator::calc);
}

在python方面,我打算:

import os
import sys
import numpy as np
import pandas as pd
sys.path.append(os.path.realpath('...'))
from one_calculator import Setup, Calculator

a_setup = Setup(1)
a_calculator = Calculator()

results = []
a_calculator.calc(a_setup, results)

results

显然结果没有传回。有没有一种巧妙的方法来做到这一点?

【问题讨论】:

  • 你的意思是a_calculator.calc(a_setup, results)
  • 是的,你是对的。我已经纠正了。谢谢!
  • 我对@9​​87654324@了解不多,但我对C++和Python都有经验。你意识到std::vector 不是python 的[],对吧?虽然pybind 可能可以将一个对象转换为另一个对象,但它们是完全不同的对象,所以我看不到通过引用传递是如何实现的。
  • 谢谢 ALX23z。我可以灵活地将数据类型 python 传递给 C++ 端。
  • 您可以使用numpy数组并通过引用传递它们。

标签: python c++ pass-by-reference pybind11


【解决方案1】:

想出了一个办法:

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>

#include "Calculator.h" // where run_calculator is

namespace py = pybind11;

// wrap c++ function with Numpy array IO
int wrapper(const std::string& input_file, py::array_t<double>& in_results) {
    if (in_results.ndim() != 2)
        throw std::runtime_error("Results should be a 2-D Numpy array");

    auto buf = in_results.request();
    double* ptr = (double*)buf.ptr;

    size_t N = in_results.shape()[0];
    size_t M = in_results.shape()[1];

    std::vector<std::vector<double> > results;

    run_calculator(input_file, results);

    size_t pos = 0;
    for (size_t i = 0; i < results.size(); i++) {
        const std::vector<double>& line_data = results[i];
        for (size_t j = 0; j < line_data.size(); j++) {
            ptr[pos] = line_data[j];
            pos++;
        }
    }
}

PYBIND11_MODULE(calculator, m) {
    // optional module docstring
    m.doc() = "pybind11 calculator plugin";

    m.def("run_calculator", &wrapper, "Run the calculator");
}

Python 端

results= np.zeros((N, M))
run_calculator(input_file, results)

这样我也不会将类 Setup 和 Calculator 暴露给 python 端。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-25
    • 2015-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-18
    相关资源
    最近更新 更多