如何将多个参数折叠为一个SWIG参数

时间:2009-08-08 00:02:34

标签: swig

我正在尝试编写一个将多个/变量参数转换为一个输入参数的类型映射。

例如,假设我有一个带矢量的函数。

void foo(vector<int> x);

我想这样称呼它(碰巧在Perl中)

foo(1,2,3,4);

typemap应该接受参数($ 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在调用foo时抑制arg2?

我不能在我的.i:

中使用它
void foo(...)

因为我希望有不同的类型映射,具体取决于foo期望的类型(int,字符串等等)。也许有办法给“......”一种类型

有办法做到这一点吗?

2 个答案:

答案 0 :(得分:2)

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'])

答案 1 :(得分:0)

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);