SWIG struct указатель как выходной параметр - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть структура:

struct some_struct_s {
   int arg1;
   int arg2;
};

У меня есть функция C:

int func(some_struct_s *output);

И то, и другое %included в моем файле SWIG.

Я хочуsome_struct_s *output должен рассматриваться как выходной параметр.Пример Python:

int_val, some_struct_output = func()

«Выходные параметры» описаны в руководстве для POD-типов (с. 10.1.3), но не для не POD-типов.

Как мне сказатьSWIG Я хочу, чтобы some_struct_s *output был выходным параметром?

1 Ответ

0 голосов
/ 20 ноября 2018

Из документации :

11.5.7 Карта типов "argout"

Карта типов "argout" используется для возврата значений из аргументов.Это чаще всего используется для написания оболочек для функций C / C ++, которые должны возвращать несколько значений.Карта типов «argout» почти всегда объединяется с картой типов «in» - возможно, чтобы игнорировать входное значение ....

Вот полный пример для вашего кода (нет проверки на ошибки для краткости)):

%module test

// Declare an input typemap that suppresses requiring any input and
// declare a temporary stack variable to hold the return data.
%typemap(in,numinputs=0) some_struct_s* (some_struct_s tmp) %{
    $1 = &tmp;
%}

// Declare an output argument typemap.  In this case, we'll use
// a tuple to hold the structure data (no error checking).
%typemap(argout) some_struct_s* (PyObject* o) %{
    o = PyTuple_New(2);
    PyTuple_SET_ITEM(o,0,PyLong_FromLong($1->arg1));
    PyTuple_SET_ITEM(o,1,PyLong_FromLong($1->arg2));
    $result = SWIG_Python_AppendOutput($result,o);
%}

// Instead of a header file, we'll just declare this code inline.
// This includes the code in the wrapper, as well as telling SWIG
// to create wrappers in the target language.
%inline %{

struct some_struct_s {
   int arg1;
   int arg2;
};

int func(some_struct_s *output)
{
    output->arg1 = 1;
    output->arg2 = 2;
    return 0;
}

%}

Демо ниже.Обратите внимание, что возвращаемое значение int, равное нулю, а также выходной параметр в виде кортежа возвращаются в виде списка.

>>> import test
>>> test.func()
[0, (1, 2)]

Если вам не нужны карты типов, вы также можете ввести код для созданиявозьмите объект и верните его, чтобы скрыть от пользователя:

%module test

%rename(_func) func; // Give the wrapper a different name

%inline %{

struct some_struct_s {
   int arg1;
   int arg2;
};

int func(struct some_struct_s *output)
{
    output->arg1 = 1;
    output->arg2 = 2;
    return 0;
}

%}

// Declare your interface
%pythoncode %{
def func():
    s = some_struct_s()
    r = _func(s)
    return r,s
%}

Демонстрация:

>>> import test
>>> r,s=test.func()
>>> r
0
>>> s
<test.some_struct_s; proxy of <Swig Object of type 'some_struct_s *' at 0x000001511D70A880> >
>>> s.arg1
1
>>> s.arg2
2

Вы можете сделать язык отображения типов независимым, если тщательно выбрать макросы SWIG:

%module test

%typemap(in,numinputs=0) struct some_struct_s *output %{
    $1 = malloc(sizeof(struct some_struct_s));
%}

%typemap(argout) struct some_struct_s* output {
    %append_output(SWIG_NewPointerObj($1,$1_descriptor,1));
}

%inline %{

struct some_struct_s {
   int arg1;
   int arg2;
};

int func(struct some_struct_s *output)
{
    output->arg1 = 1;
    output->arg2 = 2;
    return 0;
}

%}

Демо:

>>> import test
>>> r,s=test.func()
>>> r
0
>>> s
<test.some_struct_s; proxy of <Swig Object of type 'some_struct_s *' at 0x000001DD0425A700> >
>>> s.arg1
1
>>> s.arg2
2
...