我有一个与SWIG完美搭配的小项目。特别是,我的某些函数返回std::vector
s,在Python中将其转换为元组。现在,我做了很多数字运算,因此我只是将它们从C ++代码返回后,将它们转换为numpy数组。为此,我在SWIG中使用了以下内容。
%feature("pythonappend") My::Cool::Namespace::Data() const %{ if isinstance(val, tuple) : val = numpy.array(val) %}
(实际上,有几个名为Data的函数,其中一些返回浮点数,这就是为什么我检查它val
实际上是一个元组的原因。)这工作得很漂亮。
但是,我也想使用-builtin
现在可用的标志。很少调用这些Data函数,并且大多数都是交互式的,因此它们的缓慢性不是问题,但是使用内置选项可以显着加快其他缓慢循环的速度。
问题是当我使用该标志时,pythonappend功能将被静默忽略。现在,Data再次返回一个元组。有什么办法我仍然可以返回numpy数组吗?我尝试使用类型映射,但结果变得一团糟。
编辑:
Borealid很好地回答了这个问题。仅出于完整性考虑,我包括了一些相关但略微不同的类型映射,因为我是通过const引用返回的,并且我使用了vectors的向量(不要开始!)。这些差异是如此之大,以至于我不希望其他人为找出细微的差异而绊脚石。
%typemap(out) std::vector<int>& {
npy_intp result_size = $1->size();
npy_intp dims[1] = { result_size };
PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(1, dims, NPY_INT);
int* dat = (int*) PyArray_DATA(npy_arr);
for (size_t i = 0; i < result_size; ++i) { dat[i] = (*$1)[i]; }
$result = PyArray_Return(npy_arr);
}
%typemap(out) std::vector<std::vector<int> >& {
npy_intp result_size = $1->size();
npy_intp result_size2 = (result_size>0 ? (*$1)[0].size() : 0);
npy_intp dims[2] = { result_size, result_size2 };
PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_INT);
int* dat = (int*) PyArray_DATA(npy_arr);
for (size_t i = 0; i < result_size; ++i) { for (size_t j = 0; j < result_size2; ++j) { dat[i*result_size2+j] = (*$1)[i][j]; } }
$result = PyArray_Return(npy_arr);
}
编辑2:
尽管不完全符合我的期望,但也可以使用@MONK的方法(在此说明)解决类似的问题。