提升numpy示例不起作用

时间:2018-05-03 16:03:56

标签: boost-python

我尝试复制了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]

造成这种差异的原因是什么?

2 个答案:

答案 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();

在返回语句之前