Swig: 如何包装引用传递的double&?

6 投票
4 回答
8250 浏览
提问于 2025-04-16 02:42

我正在使用SWIG这个工具来让Python调用C++代码。我想知道怎么优雅地包装一个函数,这个函数通过引用返回一些值,比如:

void set(double&a) {
  a = 42.;
}

我找不到怎么做到这一点。理想情况下,我希望能在Python中使用这个函数,并且能用Python的浮点数:

>>> b = 2.
>>> set(b)
>>> print b
42.0

目前它给我报了一个错误:TypeError: in method 'TestDouble_set', argument 2 of type 'double &'

4 个回答

0

嗯,你是在用最新版本的SWIG吗?文档上似乎说明这个是可以的——来自手册的内容:

C++中的引用是被支持的,但SWIG会把它们当作指针来处理。例如,像这样的声明:

class Foo {
public:
    double bar(double &a);
}

将会通过这样的函数来访问:

double Foo_bar(Foo *obj, double *a) {
    obj->bar(*a);
}

返回引用的函数会被映射成返回指针的函数。

我不知道你在Python那边是怎么处理的……Python有没有类似于Perl的引用呢?

1

请注意,正确的解决方案依赖于SWIG提供的OUTPUT类型映射,这些类型映射在typemaps.i库中定义。这个库预先定义了上面%apply命令所使用的类型映射。

typemaps.i为C++的基本类型定义了输入和输出的类型映射(想了解更多信息可以查看上面的SWIG文档链接);不过,你需要在你的接口文件中包含这个typemaps.i库,SWIG才能使用这些类型映射。(这也是为什么有些评论者发现原来的解决方案对他们不起作用的原因。)

5

这样做:

你的 swig 接口文件:

  %include <typemaps.i>

  %apply double& INOUT { double& a };
  void set(double& a);

在 Python 脚本中的使用:

  a = 0.0
  a = set(a)
  print a

如果你的函数有返回值(不是空的),在 Python 中这样做:

  ret, a = set(a)

查看 swig 的文档,了解 typemaps 的用法。你可以为参数使用 INPUT、OUTPUT 和 INOUT。希望这对你有帮助。

注意,这个解决方案依赖于 SWIG 提供的 OUTPUT typemaps,具体定义在 typemaps.i 库中,这个库预先定义了上面 %apply 命令所用的 typemaps。

typemaps.i 为 C++ 的基本类型定义了输入/输出的 typemaps(更多信息请查看上面的 SWIG 文档链接);不过,你需要在你的接口文件中包含 typemaps.i 库,SWIG 才能使用它们。(这也是为什么有些评论者发现原来的解决方案对他们不起作用的原因。)

撰写回答