【发布时间】:2018-05-09 05:39:36
【问题描述】:
我正在尝试使用我认为在 C/C++ 中相当常见的结构,类似于以下内容:
// data.hpp
class Element {
public:
int value;
~Element() { std::cout << "In node destructor" << std::endl; }
};
class Row {
public:
Row(Element *elements) {/*initialize elements, assign ptrs*/};
std::vector<Element *> elements;
};
class Dataset {
public:
Dataset(Row *rows) {/*initialize rows, assign ptrs*/};
std::vector<Row *> rows;
};
存储指针,因为这实际上是在 CPU 和 GPU (CUDA) 上都使用的,我只想存储指针,以便每个设备可以自己找出对象的实际位置。
我的 SWIG 映射非常基础:
/* File : data.i */
%{
#include "data.hpp"
%}
%include carrays.i
%include "data.hpp"
%array_class(Node, NodeArray)
%array_class(Row, RowArray)
现在我需要将 Python/Numpy 数组转换为行数组,以便将它们传递给 Dataset 构造函数。认为这样的事情可能会起作用:
def array_to_rows(X):
nr_rows = np.shape(X)[0]
c_row_arr = example.RowArray(nr_nodes)
for r in range(nr_rows):
nr_nodes = len(X[r])
c_node_arr = example.NodeArray(nr_nodes)
for n in range(nr_nodes):
node = example.Node()
node.value = int(X[r][n])
c_node_arr[n] = node // <-- after this line node's destructor is called
c_row_arr[r] = example.Row(node_arr) // <-- after this line row's destructor is called and destructor for each Node in c_node_arr
return c_row_arr
示例调用:
import example as example
X = [
[1],
[2,3],
[4,5,6]
]
rows = array_to_rows(X)
问题是,在 Python 中的每个循环结束时,都会调用 Node 和 Row 的析构函数。所以即使我做了c_node_arr[n] = node,这个赋值也不会让Python坚持node而是删除它......
我假设这是因为 SWIG 数组正在使用指针,如果我这样做 c_node_arr[n] = node 它只会将指针设置为 node,然后将在循环结束时由 Python 释放(以及C++ 析构函数将被调用),c_node_arr 将被挂起,并带有一个指向已被释放的内存位置的指针。
有什么解决方法吗?我的方法是不是很糟糕,我应该重新考虑(如何?)。
@编辑:
目前我看到的唯一解决方法是:
1) 将 RowArray 和 NodeArray 的所有实例也保存在 Python 列表中,并在完成后释放它们
2) 将分配给RowArray 和NodeArray 从= 更改为__setitem(idx, value)
【问题讨论】: