如何在Python + SWIG中接收引用和指针参数?

8 投票
1 回答
4984 浏览
提问于 2025-04-17 17:45

我有一个C++的函数,里面有两个参数,像下面这个例子。

void func(int& n, char** data)
{
  *data = other_func1(); // returns a char array
  n = other_func2(); // returns the length of the array
}

我可以很轻松地在C或C++中使用这个函数,但我不知道如何从一个用SWIG生成的Python模块中调用它。我想我可能需要写另一个C++函数,返回比如说std::pair这样的东西。不过如果可以的话,我想知道在Python这边有没有什么解决办法。有人能帮忙吗?

1 个回答

10

在很多情况下(比如 int *n),只需要写下面的代码就可以了:

%apply int *OUTPUT { int *n };

这段代码使用了SWIG提供的一些默认类型映射,用于输出参数。(还有INOUT和INPUT,它们的用法也类似)。

不过在这个例子中,我们并没有完全符合任何预定义的情况,所以需要手动做同样的事情。基本上,每个参数需要两个类型映射:一个是输入类型映射,它会为实际的函数调用创建一个临时的东西,而不是使用真实的输入;另一个是输出类型映射,它负责把结果从临时变量传回Python。在Python中,返回多个参数时,使用元组是很合适的。

举个例子:

%module test

%typemap(in,numinputs=0) int& n (int temp) "$1 = &temp;"
%typemap(in,numinputs=0) char **data (char *temp) "$1 = &temp;"

%typemap(argout) char **data {
  %append_output(PyString_FromString(*$1));
}

%typemap(argout) int& n {
  %append_output(PyInt_FromLong(*$1));
}

%inline %{
  void foo(int& n, char **data) {
    static char str[] = "Hello world";
    *data = str;
    n = sizeof str;
  }
%}

需要注意的几点:

临时变量(int tempchar *temp)会自动重命名,这样就避免了名字冲突。%append_output是一个SWIG宏,它会扩展成将某个东西添加到Python中的$result元组的末尾。如果你的函数foo使用了动态分配的内存,你需要自己处理这个问题。freearg类型映射在输入类型映射需要动态分配内存时通常很有用。

这样就足够让我编译并运行它,像这样:

import test

len,str = test.foo()

print len
print str

撰写回答