SWIG "out" typemap возвращает адрес вместо данных - PullRequest
0 голосов
/ 11 апреля 2019

Я использую SWIG, чтобы принять список переменного размера из Python, отправить его в C ++, чтобы что-то с ним сделать, а затем отправить его обратно в Python для распечатки.

Я новичокна Python, C ++ и Swig.В настоящее время отправленный список будет обработан как векторный аргумент в моей функции C ++.После этого из функции возвращается указатель, который обрабатывается картой типов "out".

Список можно отобразить из Python, однако только если ему задан размер в карте типов out.В настоящее время мне нужно, чтобы он обрабатывал списки разных размеров.

Когда я пытаюсь добиться этого, я получаю адрес, а не список в Python.

Ниже приведен код, который работает, когдапри фиксированном размере:

>>> import customvector
>>> a = [1,2,3]
>>> customvector.summy(a)
[1.0, 2.0, 3.0]

Затем я отредактировал свой интерфейсный файл так, чтобы теперь в outmap typemap использовалось [ANY] вместо 3, чтобы можно было изменять длину.

Отредактировано customvector.i

/* File: customvector.i */
%module customvector

%{
#define SWIG_FILE_WITH_INIT
#include "customvector.h"
%}

%include "std_vector.i"
%include <stdint.i>

namespace std {
%template(Line) vector < float >;

}

%typemap(out) float* summy [ANY]{ //changed from 3 to [ANY]
  int i;
  $result = PyList_New($1_dim0);  //changed from 3 to $1_dim0
  for (i = 0; i < $1_dim0; i++) {
    PyObject *o = PyFloat_FromDouble((double) $1[i]);
    PyList_SetItem($result,i,o);
  }
}

float * summy(std::vector<float> a);

Результат от Python:

>>> import customvector
>>> a = [1,2,3]
>>> customvector.summy(a)
<Swig Object of type 'float *' at 0x000001E4E32E6420>

Это не то, что я хочу, и должно отображаться то, что было показано ранее.

Я пытался следовать документации, перечисленной где-то здесь: http://www.swig.org/Doc2.0/Typemaps.html#Typemaps_nn40 для SWIG, чтобы получить значение, отличное от выходного, но, похоже, оно не работает.

Я также натолкнулся на это решение, позволяющее изменять длину: Python / SWIG: Вывести массив , но я не уверен, как он работает, как я пытался его использовать, ноde не компилируется (говоря, что templen не определен).

Как я могу вывести из C ++ в python такие данные с переменным размером?

1 Ответ

1 голос
/ 12 апреля 2019

У вас есть неопределенное поведение в вашей реализации. Почему бы не использовать std :: vector для возвращаемого значения?

%module test

%include <std_vector.i>
%template() std::vector<float>;

%inline %{
std::vector<float> summy(std::vector<float> a)
{
    for(auto& i: a)
        i += 1;
    return a;
}
%}

Демо-версия:

>>> import test
>>> test.summy([1,2,3,4])
(2.0, 3.0, 4.0, 5.0)

Поведение по умолчанию для возвращаемых векторов - использовать кортеж. Это можно переопределить с помощью карты типов:

%module test

%include <std_vector.i>
%template() std::vector<float>;

%typemap(out) std::vector<float> %{
    $result = PyList_New($1.size());
    for (int i = 0; i < $1.size(); ++i)
        PyList_SET_ITEM($result,i,PyFloat_FromDouble($1[i]));
%}

%inline %{
#include <vector>
std::vector<float> summy(std::vector<float> a)
{
    for(auto& i: a)
        i += 1;
    return a;
}
%}

Демо-версия:

>>> import test
>>> test.summy([1,2,3,4])
[2.0, 3.0, 4.0, 5.0]
...