0

C++ で線形代数行列クラスがあり、SWIG を使用して Numpy のラッパーを作成したいと考えています。すべて正常に動作しますが、Python からの引数として参照を使用して関数を呼び出したい場合は、TypeError.

スウィッグコードは次のとおりです。

%{                                                                                                                                                                                                                                                                               
#define SWIG_FILE_WITH_INIT                                                                                                                                                                                                                                                      
%}                                                                                                                                                                                                                                                                               

%include "typemaps.i"                                                                                                                                                                                                                                                            
%include "numpy.i"                                                                                                                                                                                                                                                               
%module arraypy                                                                                                                                                                                                                                                                  
%{                                                                                                                                                                                                                                                                               
  #include "Core/array.h"                                                                                                                                                                                                                                                        
  #include "Core/array_t.h"                                                                                                                                                                                                                                                      
%}                                                                                                                                                                                                                                                                               

%fragment("NumPy_Fragments");                                                                                                                                                                                                                                                    

%init %{                                                                                                                                                                                                                                                                         
import_array();                                                                                                                                                                                                                                                                  
%}                                                                                                                                                                                                                                                                               


%typemap(in) Array<double> {                                                                                                                                                                                                                                                 
  if(is_array($input)) {                                                                                                                                                                                                                                                         
    uint size = 1;                                                                                                                                                                                                                                                               
    for(uint i=0; i<array_numdims($input); ++i)                                                                                                                                                                                                                                  
      size *= array_size($input, i);                                                                                                                                                                                                                                             
    $1.resize(size);                                                                                                                                                                                                                                                             

    memcpy($1.p, array_data($input), size*sizeof(double));                                                                                                                                                                                                                       
    $1.nd = array_numdims($input);                                                                                                                                                                                                                                               
    $1.N = size;                                                                                                                                                                                                                                                                 
    $1.d0 = array_size($input, 0);                                                                                                                                                                                                                                               
    $1.d1 = array_size($input, 1);                                                                                                                                                                                                                                               
    $1.d2 = array_size($input, 2);                                                                                                                                                                                                                                               
  }                                                                                                                                                                                                                                                                              
}                                                                                                                                                                                                                                                                                

%typemap(out) Array<double> {                                                                                                                                                                                                                                                
  long dims[3] = { $1.d0, $1.d1, $1.d2 };                                                                                                                                                                                                                                        
  PyArrayObject *a = (PyArrayObject*) PyArray_SimpleNew($1.nd, dims, NPY_DOUBLE);                                                                                                                                                                                                
  memcpy(PyArray_DATA(a), $1.p, $1.N*sizeof(double));                                                                                                                                                                                                                            
  $result = PyArray_Return(a);                                                                                                                                                                                                                                                   
}                                                                                                                                                                                                                                                                                

%inline %{                                                                                                                                                                                                                                                                       
void testing(Array<double>& a) {                                                                                                                                                                                                                                          
  std::cout << a << endl;                                                                                                                                                                                                                                                        
}                                                                                                                                                                                                                                                                                
%}

たとえば ipython を実行すると、次のようになります。

$ import arraypy
$ import numpy
$ arraypy.testing(numpy.array([1, 2, 3]))

特定のタイプマップをTypeError: in method testing, argument 1 of type ¨Array< double > &¨ 追加して作業中のタイプマップをコピーすると、何らかの形でポインターを取得したArray<double> &ため、コンパイルされません。$1それを説明すると、セグメンテーション違反が発生します。

ラッパーを参照でも動作させるにはどうすればよいですか? (もちろん、参照ではなくポインタにも同じことが言えます)

4

1 に答える 1

0

http://www.swig.org/Doc2.0/SWIGPlus.html#SWIGPlus_nn18で説明されているように、SWIG は参照をポインタに変換します。

したがって、私の最初の試みは正しかったです。参照とポインターのタイプマップをコピーするだけです。segfault は別の原因で発生しました。すべてを少し良くするために、fragmet を使用できます。

于 2013-10-23T13:15:46.213 に答える