2014-06-23 28 views
1

我在使用SWIG使用Eigen(線性代數封裝)封裝一個小型項目時遇到了問題。我得到一個我不明白的python錯誤,在網上找不到太多內容 - 但我懷疑某處存在一些C++內存損壞。我煮下來到一個玩具例子..但遺憾的是它仍然是合理的長:使用Swig封裝Eigen/C++與Python的錯誤

--- testfunc.cxx ----

#include "Eigen/Dense" 

Eigen::VectorXd test(Eigen::MatrixXd data){ 
     Eigen::VectorXd temp; 
     return temp; 
} 

--- testswig.i ---- -

%module testswig 

%{ 
#define SWIG_FILE_WITH_INIT 
#include "Eigen/Core" 
#include <Python.h> 
#include <numpy/arrayobject.h> 
#include "testfunc.cxx" 

%} 

%init 
%{ 
    import_array(); 
%} 

%include "numpy.i" 

%typemap(out) Eigen::VectorXd 
{ 
    npy_intp dims[1] = {$1.size()}; 
    PyObject* array = PyArray_SimpleNew(1, dims, NPY_DOUBLE); 
    double* data = ((double *)PyArray_DATA(array)); 
    for (int i = 0; i != dims[0]; ++i){ 
     *data++ = $1.data()[i]; 
    } 
    $result = array; 
} 

%typemap(in) Eigen::MatrixXd (Eigen::MatrixXd TEMP) 
{ 

    int rows = 0; 
    int cols = 0; 

    rows = PyArray_DIM($input,0); 
    cols = PyArray_DIM($input,1); 

    PyArrayObject* temp; 
    PyArg_ParseTuple($input, "O", &temp); 

    TEMP.resize(rows,cols); 
    TEMP.fill(0); 

    double * values = ((double *) PyArray_DATA($input)); 
    for (long int i = 0; i != rows; ++i){ 
     for(long int j = 0; j != cols; ++j){ 
      // std::cout << "data " << data[i] << std::endl; 
      TEMP(i,j) = values[i*rows+j]; 
     } 
    } 

} 

%include "testfunc.cxx" 

--- setup.py ----

from distutils.core import setup, Extension 
import numpy 
numpyinclude = numpy.__file__[:-12] + 'core/include/' 
testswig = Extension('_testswig', 
        sources=['testswig_wrap.cxx'], 
        include_dirs=['../', numpyinclude]) 

setup (name = 'testswig', 
     version = '0.1', 
     author  = "NoName", 
     description = """ """, 
     ext_modules = [testswig], 
     py_modules = ["testswig"]) 

-----建築------

我在包含所有3個文件和包含Eigen標題的文件夾'Eigen'的文件夾中構建此文件。這些命令是:

swig -c++ -python -I./ testswig.i 
python setup.py install 

-------錯誤----------

然後我運行包含

import testswig 
import numpy as np 
print testswig.test(np.array([[2,3],[4,5]])) 

一個Python文件,該文件給出錯誤「SystemError:新樣式getargs格式但參數不是元組」。

注意幾件事: 1)相同的命令直接從python解釋器運行良好。 2)如果函數沒有返回一個Eigen :: VectorXd,或者沒有使用一個Eigen:MatrixXd,它可以正常工作。

謝謝你的時間。

+0

您的python安裝版本3或以上?如果是的話,當你打電話給SWIG時你需要-py3。 – Flexo

+0

不,但很高興知道(您的解決方案是完美的)。 – thebigdog

回答

3

在你的類型表您有:

PyArrayObject *temp; 
PyArg_ParseTuple($input, "O", &temp); 

這是不正確 - $input是已經從參數在這個階段提取的PyObject,但不是一個元組,所以要:

PyArrayObject *temp=NULL; 
if (PyArray_Check($input)) 
    temp = (PyArrayObject*)$input; 

驗證它是正確的類型,然後如果是,則進行強制轉換。

+1

請注意,雖然你實際上並沒有在任何地方使用溫度。 – Flexo

+0

謝謝柔印!在我發佈這個問題之後,我看到我沒有使用它(從我的更大的例子中翻譯得不好),但這是導致這個問題的第一個問題。我誤解了$ $所指的是什麼。 – thebigdog

+0

出於興趣 - 你能解釋一下我用上面的代碼得到的Python錯誤嗎? PyArg_ParseTuple是否會導致提前刪除某些內容? – thebigdog