在模板中包装 C++ 模板构造函数 class

Wrapping C++ template constructors in template class

我有一个复杂的 c++ 库,我需要将其公开给 java android 应用程序。这个 C++ 库由标准 C++ classes 和 C++ class 模板组成。

库中的一个模板具有模板构造函数。

因为一个例子胜过千言万语:

namespace NS1 {

    template < class T >
    class Bar {

    protected:

        T mVal;

    public:

        template< class OtherType >
        Bar (const Bar<OtherType>& pOther) {
            mVal = pOther.mVal;
        }

    };

    class A {
    };

    class B : public A {};
}

我使用以下 swig 接口文件片段包装它们:

%extend NS1::Bar< A > {
    %template(Abar) NS1::Bar::Bar<NS1::A>;
    %template(ABar) NS1::Bar::Bar<NS1::B>;
};
%template(ABar) NS1::Bar< NS1::A >;

%extend NS1::Bar<B> {
    %template(BBar) NS1::Bar::Bar<NS1::B>;
};
%template(BBar) NS1::Bar<NS1::B>;

我希望包装器包含模板构造函数的包装:

public class ABar {
    public ABar (ABar other) {...}
    public ABar (BBar other) {...}
}

没关系,问题是扩展指令似乎忽略了模板参数,并用这些扩展了 Bar 模板的每个实例。 IE。 BBar java class 看起来像这样:

public class BBar {
    public BBar (ABar other) {...}
    public BBar (BBar other) {...}
}

在那种情况下这是不正确的。

如何 "bind" 扩展到特定的模板实例化?

注:

在 %extend 指令 (%extend NS1::Bar<NS1::A>{...}) 中使用命名空间会导致 Swig 中的断言失败。

我试过 swig 2.0.12 和 3.0.8

有人知道吗?

我已经按照您希望的方式使用 SWIG 3.x 实现了这一点。这里绝对是过于敏感了,我认为归结为三点:

  1. 与名称空间保持一致。要么始终使用完全限定版本,要么始终将所有内容写入 .i 文件中的命名空间。
  2. %extend 中将构造函数称为 Bar 而不是 Bar::Bar。 (根据 std::pair example in the documentation
  3. 在有选择地扩展任何模板之前实例化所有模板。

我不完全确定是否所有这些都是强制性的,但它们肯定足以让它在这里发挥作用。所以我的工作示例如下所示:

%module test

%include "test.hh"

%template(ABar) NS1::Bar< NS1::A >;
%template(BBar) NS1::Bar<NS1::B>;

namespace NS1 {

%extend Bar< A > {
    %template(ABar) Bar<A>;
    %template(ABar) Bar<B>;
};

%extend Bar<B> {
    %template(BBar) Bar<B>;
};
} // NS1

使用 test.hh 作为您显示的逐字复制的 C++ 代码,这会生成正常的 Java/JNI。

不过,遵循上述准则,以下内容也可以使用:

%module test

%include "test.hh"

%template(ABar) NS1::Bar< NS1::A >;
%template(BBar) NS1::Bar<NS1::B>;

%extend NS1::Bar<NS1::A> {
    %template() Bar<NS1::A>;
    %template() Bar<NS1::B>;
};

%extend NS1::Bar<NS1::B> {
    %template() Bar<NS1::B>;
};