Return 一个 std::vector 到 python 作为一个 numpy 数组
Return an std::vector to python as a numpy array
使用 Pybind11,我试图将一个 numpy 数组传递给 c++ 到 std::vector
,将其乘以 2,然后 return 这个 std::vector
到 python 作为一个 numpy 数组。
我已经迈出了第一步,但第三步却在做一些奇怪的事情。为了将它传递回去,我使用了: py::array ret = py::cast(vect_arr);
奇怪的是,我的意思是 return 在 Python 中编辑的向量没有正确的尺寸或正确的顺序。
例如,我有一个数组:
[[ 0.78114362 0.06873818 1.00364053 0.93029671]
[ 1.50885413 0.38219005 0.87508337 2.01322396]
[ 2.19912915 2.47706644 1.16032292 -0.39204517]]
和代码 returns:
array([[ 1.56228724e+000, 3.01770826e+000, 4.39825830e+000,
5.37804299e+161],
[ 1.86059342e+000, 4.02644793e+000, -7.84090347e-001,
1.38298992e-309],
[ 1.75016674e+000, 2.32064585e+000, 0.00000000e+000,
1.01370255e-316]])
我已阅读文档,但我无法理解其中的大部分内容。
这里有一个例子可以尝试:
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>
#include <Python.h>
namespace py = pybind11;
py::module nn = py::module::import("iteration");
py::array nump(py::array arr){
auto arr_obj_prop = arr.request();
//initialize values
double *vals = (double*) arr_obj_prop.ptr;
unsigned int shape_1 = arr_obj_prop.shape[0];
unsigned int shape_2 = arr_obj_prop.shape[1];
std::vector<std::vector <double>> vect_arr( shape_1, std::vector<double> (shape_2));
for(unsigned int i = 0; i < shape_1; i++){
for(unsigned int j = 0; j < shape_2; j++){
vect_arr[i][j] = vals[i*shape_1 + j*shape_2] * 2;
}
}
py::array ret = py::cast(vect_arr); //py::array(vect_arr.size(), vect_arr.data());
return ret;
}
PYBIND11_MODULE(iteration_mod, m) {
m.doc() = "pybind11 module for iterating over generations";
m.def("nump", &nump,
"the function which loops over a numpy array");
}
和 Python 代码:
import numpy as np
import iteration_mod as i_mod
class iteration(object):
def __init__(self):
self.iterator = np.random.normal(0,1,(3,4))
def transform_to_dict(self):
self.dict = {}
for i in range(self.iterator.shape[0]):
self.dict["key_number_{}".format(i)] = self.iterator[i,:]
return self.dict
def iterate_iterator(self):
return i_mod.nump(self.iterator)
def iterate_dict(self):
return i_mod.dict(self)
a = iteration()
print(a.iterator)
print(a.iterate_iterator())
所有这些编译:c++ -O3 -Wall -fopenmp -shared -std=c++11 -fPIC
python3 -m pybind11 --includes iteration_mod.cpp -o iteration_mod.so
std::vector<std::vector<double>>
没有二维内置数组的内存布局,因此 py::array(vect_arr.size(), vect_arr.data());
将无法工作。
看起来 py::cast 确实进行了正确的复制转换并将值从向量传播到新的 numpy 数组,但是这一行:
vect_arr[i][j] = vals[i*shape_1 + j*shape_2] * 2;
不对。应该是:
vect_arr[i][j] = vals[i*shape_2 + j] * 2;
使用 Pybind11,我试图将一个 numpy 数组传递给 c++ 到 std::vector
,将其乘以 2,然后 return 这个 std::vector
到 python 作为一个 numpy 数组。
我已经迈出了第一步,但第三步却在做一些奇怪的事情。为了将它传递回去,我使用了: py::array ret = py::cast(vect_arr);
奇怪的是,我的意思是 return 在 Python 中编辑的向量没有正确的尺寸或正确的顺序。
例如,我有一个数组:
[[ 0.78114362 0.06873818 1.00364053 0.93029671]
[ 1.50885413 0.38219005 0.87508337 2.01322396]
[ 2.19912915 2.47706644 1.16032292 -0.39204517]]
和代码 returns:
array([[ 1.56228724e+000, 3.01770826e+000, 4.39825830e+000,
5.37804299e+161],
[ 1.86059342e+000, 4.02644793e+000, -7.84090347e-001,
1.38298992e-309],
[ 1.75016674e+000, 2.32064585e+000, 0.00000000e+000,
1.01370255e-316]])
我已阅读文档,但我无法理解其中的大部分内容。
这里有一个例子可以尝试:
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>
#include <Python.h>
namespace py = pybind11;
py::module nn = py::module::import("iteration");
py::array nump(py::array arr){
auto arr_obj_prop = arr.request();
//initialize values
double *vals = (double*) arr_obj_prop.ptr;
unsigned int shape_1 = arr_obj_prop.shape[0];
unsigned int shape_2 = arr_obj_prop.shape[1];
std::vector<std::vector <double>> vect_arr( shape_1, std::vector<double> (shape_2));
for(unsigned int i = 0; i < shape_1; i++){
for(unsigned int j = 0; j < shape_2; j++){
vect_arr[i][j] = vals[i*shape_1 + j*shape_2] * 2;
}
}
py::array ret = py::cast(vect_arr); //py::array(vect_arr.size(), vect_arr.data());
return ret;
}
PYBIND11_MODULE(iteration_mod, m) {
m.doc() = "pybind11 module for iterating over generations";
m.def("nump", &nump,
"the function which loops over a numpy array");
}
和 Python 代码:
import numpy as np
import iteration_mod as i_mod
class iteration(object):
def __init__(self):
self.iterator = np.random.normal(0,1,(3,4))
def transform_to_dict(self):
self.dict = {}
for i in range(self.iterator.shape[0]):
self.dict["key_number_{}".format(i)] = self.iterator[i,:]
return self.dict
def iterate_iterator(self):
return i_mod.nump(self.iterator)
def iterate_dict(self):
return i_mod.dict(self)
a = iteration()
print(a.iterator)
print(a.iterate_iterator())
所有这些编译:c++ -O3 -Wall -fopenmp -shared -std=c++11 -fPIC
python3 -m pybind11 --includes iteration_mod.cpp -o iteration_mod.so
std::vector<std::vector<double>>
没有二维内置数组的内存布局,因此 py::array(vect_arr.size(), vect_arr.data());
将无法工作。
看起来 py::cast 确实进行了正确的复制转换并将值从向量传播到新的 numpy 数组,但是这一行:
vect_arr[i][j] = vals[i*shape_1 + j*shape_2] * 2;
不对。应该是:
vect_arr[i][j] = vals[i*shape_2 + j] * 2;