Как я могу свернуть несколько аргументов в один параметр SWIG - PullRequest
1 голос
/ 08 августа 2009

Я пытаюсь написать карту типов, которая преобразует несколько аргументов / переменных в один входной параметр.

Например, скажем, у меня есть функция, которая принимает вектор.

void foo(vector<int> x);

И я хочу назвать это так (случается в Perl)

foo(1,2,3,4);

Карта типов должна принимать аргументы ($ argnum, ...), собирать их в один вектор и затем передавать их в foo.

Пока у меня есть это:

typedef vector<int> vectori;
%typemap(in) (vectori) {
  for (int i=$argnum-1; i<items; i++) {
      $1->push_back( <argv i> );   // This is language dependent, of course.
  }
}

Это будет работать, за исключением того, что SWIG проверяет количество аргументов

if ((items < 1) || (items > 1)) {
  SWIG_croak("Usage: foo(vectori);");
}

Если я это сделаю:

 void foo(vectori, ...);

SWIG ожидает вызова foo с двумя аргументами.

 foo(arg1, arg2);

Может быть, есть способ сообщить SWIG, что нужно подавить arg2 из вызова foo?

Я не могу использовать это в моем .i:

void foo(...)

потому что я хочу, чтобы у меня были разные карты типов, в зависимости от типов, которые ожидает foo (массив int, строки, что угодно). Может быть, есть способ дать тип "..."

Есть ли способ сделать это?

Ответы [ 2 ]

2 голосов
/ 27 июня 2012

SWIG имеет встроенную поддержку для некоторых классов STL. Попробуйте это для своего SWIG-файла .i:

%module mymod

%{
#include <vector>
#include <string>
void foo_int(std::vector<int> i);
void foo_str(std::vector<std::string> i);
%}

%include <std_vector.i>
%include <std_string.i>
// Declare each template used so SWIG exports an interface.
%template(vector_int) std::vector<int>;
%template(vector_str) std::vector<std::string>;

void foo_int(std::vector<int> i);
void foo_str(std::vector<std::string> i);

Затем вызовите его с синтаксисом массива на выбранном языке:

#Python
import mymod
mymod.foo_int([1,2,3,4])
mymod.foo_str(['abc','def','ghi'])
0 голосов
/ 25 ноября 2009

SWIG определяет количество аргументов в то время, когда SWIG генерирует привязки. SWIG обеспечивает некоторую ограниченную поддержку списков переменных аргументов, но я не уверен, что это правильный подход. Если вам интересно, вы можете прочитать об этом в разделе документации SWIG vararg .

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

%typemap(in) vectori (vector<int> tmp)
{
    if (!SvROK($input))
        croak("Argument $argnum is not a reference.");

    if (SvTYPE(SvRV($input)) != SVt_PVAV) 
        croak("Argument $argnum is not an array.");

    $1 = &$tmp;

    AV *arrayValue = (AV*)SvRV($input);
    int arrayLen = av_len(arrayLen);

    for (int i=0; i<=arrayLen; ++i) 
    {
        SV* scalarValue = av_fetch(arrayValue , i, 0);
        $1->push_back( SvPV(*scalarValue, PL_na) );
    }
};

Тогда из Perl вы будете использовать обозначение массива:

@myarray = (1, 2, 3, 4);
foo(\@myarray);
...