Boost numpy 示例不起作用

Boost numpy example does not work

我尝试重现 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]

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

这周我遇到了同样的问题。为了解决我的问题,我使用动态内存:

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;
}

我认为根据这个答案的区别:是:

The difference between declaring an array as

int array[n];

and

int* array = malloc(n * sizeof(int));

In the first version, you are declaring an object with automatic storage duration. This means that the array lives only as long as the function that calls it exists. In the second version, you are getting memory with dynamic storage duration, which means that it will exist until it is explicitly deallocated with free.

我将在接下来的几周内花更多时间看看这是否也适用于矩阵。

编辑

或者您可以使用来自 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;
}

我假设(暂时)通过使用增强功能,您将能够避免内存冲突。

在 return 之前创建对数组的新引用解决了问题。好消息是 np::ndarray 有一个 copy() 方法可以实现完全相同的事情。因此,您应该添加

np::ndarray new_array = array.copy();

在 return 声明之前