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

时间:2016-12-02 14:43:50

标签: java c++ templates swig

我有一个复杂的c ++库,我需要向Java android应用程序公开。该C ++库由标准C ++类和C ++类模板组成。

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

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

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) {...}
}

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

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

在这种情况下哪个不正确。

我怎样才能&#34;绑定&#34;扩展到特定的模板实例化?

注意:

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

我试过swig 2.0.12和3.0.8

有人知道吗?

1 个答案:

答案 0 :(得分:1)

当你希望使用SWIG 3.x时,我得到了这个工作。它在这里肯定过于敏感,我认为它归结为三件事:

  1. 与命名空间保持一致。要么始终使用完全限定版本,要么始终在.i文件中的名称空间内写入所有内容。
  2. Bar内将构造函数称为Bar::Bar而不是%extend。 (根据std::pair example in the documentation
  3. 在有选择地扩展之前实例化所有模板。
  4. 我不完全确定所有这些都是强制性的,但它们肯定足以让它在这里工作。所以我的工作示例如下:

    %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>;
    };