首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >有没有办法将pythonappend与SWIG的新内置功能一起使用?

有没有办法将pythonappend与SWIG的新内置功能一起使用?
EN

Stack Overflow用户
提问于 2012-02-14 08:19:21
回答 1查看 2K关注 0票数 77

我有一个小项目,可以很好地使用SWIG。特别是,我的一些函数返回Python,它们在std::vector中被转换为元组。现在,我做了很多数值运算,所以我只是让SWIG在它们从c++代码返回后将它们转换成numpy数组。为了做到这一点,我在SWIG中使用了类似于下面的内容。

代码语言:javascript
复制
%feature("pythonappend") My::Cool::Namespace::Data() const %{ if isinstance(val, tuple) : val = numpy.array(val) %}

(实际上,有几个名为Data的函数,其中一些函数返回浮点数,这就是为什么我检查val实际上是一个元组的原因。)这真是太棒了。

但是,我也想使用现在可用的-builtin标志。对这些数据函数的调用很少,而且大多是交互式的,所以它们的速度并不是问题,但还有其他慢循环可以使用内置选项显着提高速度。

问题是,当我使用这个标志时,pythonappend特性被忽略了。现在,Data只是再次返回一个元组。有没有办法我仍然可以返回numpy数组?我试着使用类型映射,但它变成了一个巨大的混乱。

编辑:

Borealid很好地回答了这个问题。为了完整起见,我包含了两个相关但略有不同的类型映射,这是我需要的,因为我通过常量引用返回,并且我使用向量的向量(不要开始!)。这些都是不同的,我不想让任何其他人在尝试弄清楚细微的差异时犯错。

代码语言:javascript
复制
%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的方法(explained here)也可以解决类似的问题。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-01-11 01:18:28

我同意您的观点,使用typemap会有点混乱,但这是完成此任务的正确方法。您也是对的,SWIG文档没有直接指出%pythonappend-builtin不兼容,但这是非常隐含的:%pythonappend添加到了Python代理类中,而Python代理类与-builtin标志一起根本不存在。

以前,您所做的是让SWIG将C++ std::vector对象转换为Python元组,然后将这些元组传递回numpy -在那里它们再次被转换。

您真正想要做的是在C级别上转换它们一次。

下面是将所有std::vector<int>对象转换为NumPy整数数组的代码:

代码语言:javascript
复制
%{
#include "numpy/arrayobject.h"
%}

%init %{
    import_array();
%}

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

它使用C级numpy函数来构造和返回一个数组。在顺序上,它:

  • 可确保NumPy的arrayobject.h文件包含在C++输出文件中
  • 会导致在加载Python模块时调用import_array (否则,所有NumPy方法都会将std::vector<int>的任何返回结果写入到带有typemap

std::vector<int>数组中

这段代码应该放在包含返回std::vector<int>的函数的%import头之前。除了这个限制,它是完全自包含的,所以它不应该给你的代码库添加太多主观的“混乱”。

如果你需要其他的向量类型,你只需要修改NPY_INT以及所有的int*int位,否则就会重复上面的函数。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9270052

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档