提升numpy示例不起作用

问题描述 投票:0回答:2

我尝试再现一些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]

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

boost-python
2个回答
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));

在第一个版本中,您声明一个具有自动存储持续时间的对象。这意味着只要存在调用它的函数,该数组就会存在。在第二个版本中,您将获得具有动态存储持续时间的内存,这意味着它将一直存在,直到它被显式释放为free。

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

编辑

或者你可以使用boost like list中的动态结构:

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

这项工作也适用于Matrix,例如:

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函数,您将能够避免内存冲突。


0
投票

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

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

在返回声明之前

© www.soinside.com 2019 - 2024. All rights reserved.