Ошибка переноса собственного / C в Python с использованием Swig

#python #c #swig

#python #c #swig

Вопрос:

У меня возникли проблемы с переносом небольшого проекта, который использует собственный файл (пакет линейной алгебры) с использованием SWIG. Я получаю ошибку python, которую я не понимаю и не могу найти много информации в Интернете, но я подозреваю, что где-то есть повреждение памяти C . Я свел это к игрушечному примеру.. но, к сожалению, это все еще достаточно долго:

— 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", amp;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’, содержащей собственные заголовки. Команды :

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

——- ошибка ———-

Затем я запускаю файл python, содержащий

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

Что выдает ошибку «SystemError: новый формат getargs в стиле, но аргумент не является кортежем».

Обратите внимание на несколько вещей: 1) Те же команды отлично выполняются непосредственно из интерпретатора python. 2) Если функция не возвращает собственный файл ::VectorXd или не принимает собственный файл:MatrixXd, она работает нормально.

Спасибо за ваше время.

Комментарии:

1. Установлен ли ваш python версии 3 или выше? Вам понадобится -py3 при вызове SWIG, если он есть.

2. Нет, но полезно знать (ваше решение ниже идеально).

Ответ №1:

В вашей in typemap у вас есть:

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

Это неверно — $input это PyObject, который уже был извлечен из аргументов на этом этапе, но не кортеж, поэтому вы хотите:

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

Чтобы убедиться, что это правильный тип, а затем выполнить приведение, если это так.

Комментарии:

1. Обратите внимание, что на самом деле вы нигде не используете temp.

2. Спасибо Flexo! Я видел, что не использовал его после того, как опубликовал вопрос (плохой перевод из моего более крупного примера), но это была первая проблема, которая вызывала проблемы. Я неправильно понял, на что указывал $input .

3. Из интереса — можете ли вы пролить свет на ошибку Python, которую я получаю с помощью приведенного выше кода? Является ли PyArg_ParseTuple причиной раннего удаления чего-либо?

4. Просто внутренне он выполняет проверку типа, чтобы увидеть, действительно ли вы дали ему кортеж, и вызывает исключение, если это не так.