#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. Просто внутренне он выполняет проверку типа, чтобы увидеть, действительно ли вы дали ему кортеж, и вызывает исключение, если это не так.