我尝试复制了here所描述的一些示例,但我在下面的代码中遇到了以下问题,该代码只是通过复制粘贴链接页面的相关部分来编写。
#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
#include <iostream>
using namespace std;
namespace p = boost::python;
namespace np = boost::python::numpy;
np::ndarray test()
{
int data[] = {1,2,3,4,5};
p::tuple shape = p::make_tuple(5);
p::tuple stride = p::make_tuple(sizeof(int));
p::object own;
np::dtype dt = np::dtype::get_builtin<int>();
np::ndarray array = np::from_data(data, dt, shape,stride,own);
std::cout << "Selective multidimensional array :: "<<std::endl
<< p::extract<char const *>(p::str(array)) << std::endl ;
return array;
}
BOOST_PYTHON_MODULE(test_module)
{
using namespace boost::python;
// Initialize numpy
Py_Initialize();
boost::python::numpy::initialize();
def("test", test);
}
当我编译为共享库并在python中加载模块时,
import test_module as test
print(test.test())
似乎ndarray
由C ++代码正确创建,但python收到的版本是垃圾;打印的数组是:
[1 2 3 4 5]
[2121031184 32554 2130927769 32554 0]
造成这种差异的原因是什么?
答案 0 :(得分:1)
这周我遇到了同样的问题。为了解决我的问题,我使用了动态内存:
np::ndarray test(){
int *data = malloc(sizeof(int) * 5);
for (int i=0; i < 5; ++i){
data[i] = i + 1;
}
p::tuple shape = p::make_tuple(5);
p::tuple stride = p::make_tuple(sizeof(int));
p::object own;
np::dtype dt = np::dtype::get_builtin<int>();
np::ndarray array = np::from_data(data, dt, shape, stride, own);
return array;
}
我认为根据此答案:https://stackoverflow.com/a/36322044/4637693的不同之处是:
将数组声明为
的区别int array[n];
和
int* array = malloc(n * sizeof(int));
在第一个版本中,您要声明一个具有自动存储持续时间的对象。这意味着数组仅在调用它的函数存在的情况下存在。在第二个版本中,您将获得具有动态存储持续时间的内存,这意味着该内存将一直存在,直到将其显式释放为空闲为止。
在接下来的几周内,我将花费更多时间来看看这是否也适用于矩阵。
编辑
或者您可以使用类似boost这样的动态结构:
np::ndarray test(){
boost::python::list my_list;
for (int i=0; i < 5; ++i){
my_list.append(i + 1);
}
np::ndarray array = np::from_object(my_list);
return array;
}
例如,此工作也适用于矩阵
np::ndarray test(){
//This will use a list of tuples
boost::python::list my_list;
for (int i=0; i < 5; ++i){
my_list.append(boost::python::make_tuple(i + 1, i, i-1));
}
//Just convert the list to a NumPy array.
np::ndarray array = np::from_object(my_list);
return array;
}
我暂时(假设)通过使用boost函数可以避免内存冲突。
答案 1 :(得分:0)
在返回数组之前创建对数组的新引用解决了该问题。好消息是np::ndarray
具有copy()
方法,可以实现完全相同的效果。因此,您应该添加
np::ndarray new_array = array.copy();
在返回语句之前