如何使用SWIG为C++模板类创建一个调度包装器类

3
我们正在尝试使用SWIG将C++模板库封装为不同语言(Python、Java、R等)的库。我们不想在目标语言中为每个类型实例化使用不同的类名。相反,我们希望获得一个单一的分派类(就像SWIG处理重载函数一样)。由于我们有许多类,我们还想让SWIG从给定的C++头文件中提取类和方法。
例如:假设一个只读的C++头文件包含:
template< typename T >
class Foo {
    Foo(const T * t);
    const T* getVal() const;
    void setVal(const T* t);
};

现在我们想要为SWIG编写一个接口文件,创建一个能够调用正确模板实例的单个类(如果在每个函数调用中发生也可以)。在Python中,我们想要允许像这样的操作。
from foo import Foo
v_int = Foo(1)
v_int.setVal(v_int.getVal())
v_str = Foo("string")
v_str.setVal(v_str.getVal())

我有一些手动完成这个操作的思路,但基本上意味着我必须在C++中编写自己的包装类,并将模板类定义的每个成员函数都包含在其中。随着我们想要包装的类数量增多,这变得不切实际。

有什么想法吗?例如,在SWIG接口文件中是否有一种“迭代”所有成员函数的方法?

1个回答

0

我自己没有测试过,但是关于C++模板的SWIG文档似乎表明这很容易,你只需要告诉SWIG哪些类可以接受该模板。将那里的示例适应到您的示例头文件中,您的SWIG文件将如下所示:

%module foo
%{
#include "foo.h"
%}

template< typename T>
class Foo {
    Foo(const T *t);
    const T* getVal() const;
    void setVal(const T* t);
};

%template(i) foo<int>;
%template(str) foo<string>;

对于您想要与模板一起使用的任何其他类型,可以添加类似的行。

然后您可以在Python中像这样使用它:

>>> v_int = Foo.i(1)
>>> v_int.setVal(v_int.getVal())
>>> v_str = Foo.str("string")
>>> v_str.setVal(v_str.getVal())

现在,我知道你说你不想为每个实例使用不同的类名,而且由于在创建对象时必须决定对象类型,这并不是您在本机C++中获得的完全透明的模板使用。但它似乎相当接近,并且比为所有内容编写包装器类要少得多。


1
谢谢。不幸的是,这并不完全是我要找的。不能使用'int'或'double'来命名模板实例化。它还需要命名类("%template(asint) Foo<int>")。此外,每个模块有多个类,因此语法会变得冗长,例如: v_int = foo.FooAsInt(1) v_str = foo.FooAsStr("str") - Frank
啊,是的,我匆忙编辑那段代码时犯了一些错误。感谢您指出了这些问题,我已经修改了它,以便它至少是一个有效示例,适用于某个人的这种技术。如果这种方法对您来说不够简洁,那么抱歉,我已经没有更好的想法了。 - Chris H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接