SWIG 输入文件和带有 numpy 的向量。使用 % 应用?

Posted

技术标签:

【中文标题】SWIG 输入文件和带有 numpy 的向量。使用 % 应用?【英文标题】:SWIG input files and Vectors with numpy. Using %apply? 【发布时间】:2015-09-21 17:28:32 【问题描述】:

我正在尝试让我的 C++ 代码使用 Swig 提供一个 numpy 数组。一切都设置得很好,但是当我通过 python 运行我的代码时,我得到了一个 SwigPyObject。我似乎想不出正确的 SWIG 输入文件。我的函数如下所示:

    double*** runshapes(vector<vector<vector<double> > > &array3d,
            double T,
            double lam,
            double Vel)...

我的 .i 文件如下所示:

%module runshapes
%
#define SWIG_FILE_WITH_INIT
#include "runshapes.h"
%
%include "numpy.i"

%init %
import_array(); 
%

%include "std_vector.i"
%include "std_string.i"
// Instantiate templates used by example

namespace std 
   %template(DoubleVector) vector<double>;
   %template(VecVecdouble) vector< vector<double> >;
   %template(VecVecVecdouble) vector< vector< vector<double> > >;


%include "runshapes.h"

它似乎理解向量,但输出(应该是 3D 数组)作为 SwigPyObject 输出。

如果这样可以简化问题,我可以将输出设为 3D 矢量 :)

感谢您的帮助! 克里斯蒂娜

【问题讨论】:

嘿,@克里斯蒂娜。使用std::vector 总是会复制数据,不可能使用指针创建std::vector 而无需复制。我通常使用llvm 中的ArrayRef 或为std::vector 制作一个包装器,并使用numpy.i 中的常规方法进行swigging。如果您愿意,我可以为此发布解决方案。挺好看的 【参考方案1】:

我通常使用 POD 类型使用 NumPy 类型映射来包装接口,如下所示。

vector3.h

#pragma once

#include <stddef.h>

int runshapes_wrap(const double* idata,
                   const size_t inx,
                   const size_t iny,
                   const size_t inz,
                   double** odata,
                   size_t* onx,
                   size_t* ony,
                   size_t* onz);

vector3.cpp

#include "vector3.h"

#include <stdio.h>
#include <malloc.h>

int runshapes_wrap(const double* idata,
                   const size_t inx,
                   const size_t iny,
                   const size_t inz,
                   double** odata,
                   size_t* onx,
                   size_t* ony,
                   size_t* onz) 
  // Note this one allocates
  size_t nx = 10;
  size_t ny = 20;
  size_t nz = 30;

  *odata = (double*) malloc(sizeof(double)*nx*ny*nz);
  *onx = nx;
  *ony = ny;
  *onz = nz;

  // Do whatever
  printf("inx,iny,inz: %zu, %zu, %zu\n",nx,ny,nz);
  return 0;

vector3.i

%module(docstring="This is a Python wrapper for Sofus") swig_vector
%
  #define SWIG_FILE_WITH_INIT  
  #include "vector3.h"
%

%include "numpy.i"

%init
%
  import_array();
%

%apply (double** ARGOUTVIEWM_ARRAY3, size_t* DIM1, size_t* DIM2, size_t* DIM3) (double** odata, size_t* onx, size_t* ony, size_t* onz)

%apply (double* IN_ARRAY3, int DIM1, int DIM2, int DIM3) (const double* idata, const size_t inx, const size_t iny, const size_t inz);

%include "vector3.h"

请注意,类型映射 ARGOUTVIEWM_ARRAY3 确保在 Python 中删除相应的 NumPy 数组时删除分配的数据。使用模板,这可以变得非常紧凑,但是您需要为每个模板实例化一个类型映射。

# setup.py

from distutils.core import setup, Extension

setup(name="swig_vector",
      py_modules=['swig_vector'],
      ext_modules=[Extension("_swig_vector",
                     ["vector3.i", "vector3.cpp"],
                     swig_opts=['-c++'],
    extra_compile_args=['--std=c++11']
                  )]

)

使用python setup.py build_ext --inplace 执行最后一个脚本会生成准备好测试功能的库

【讨论】:

以上是关于SWIG 输入文件和带有 numpy 的向量。使用 % 应用?的主要内容,如果未能解决你的问题,请参考以下文章

带有 SWIG 的 C++ 数组到 Numpy 的 TypeError 问题

swig numpy 多个矩阵和数组输入

如何使用 SWIG 将 numpy 数组转换为 vector<int>&(参考)

使用 SWIG 控制器将 python 中的 numpy 函数传递给 C++

SWIG:将 2d numpy 数组传递给 C 函数 f(double a[])

将 C/C++ 向量快速转换为 Numpy 数组