简体   繁体   English

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

[英]Wrapping C++ template constructors in template class

I have a complex c++ library that I need to expose to a java android application. 我有一个复杂的c ++库,我需要向Java android应用程序公开。 This C++ library consists of standard C++ classes and C++ class templates. 该C ++库由标准C ++类和C ++类模板组成。

One of the templates in the library has a template constructor. 库中的一个模板有一个模板构造函数。

Because an example is worth a thousand words: 因为一个例子胜过千言万语:

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

I wrap these using the following swig interface file snippet: 我使用以下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>;

I'd like the wrapper to include wrapping of the template constructor: 我希望包装器包含模板构造函数的包装:

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

This is alright, the issue is that the extend directive seems to ignore the template parameter, and extends every instantiation of the Bar template with these. 这没关系,问题是extend指令似乎忽略了模板参数,并使用这些参数扩展了Bar模板的每个实例。 Ie the BBar java class looks like this: BBar java类看起来像这样:

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

Which is incorrect in that case. 在这种情况下哪个是不正确的。

How can I "bind" the extend to a specific template instantiation ? 如何将扩展“绑定”到特定的模板实例化?

Note: 注意:

Using the namespace in the %extend directive ( %extend NS1::Bar<NS1::A>{...} ) causes an assert in Swig to fail. 在%extend指令中使用命名空间( %extend NS1::Bar<NS1::A>{...} )会导致Swig中的断言失败。

I have tried with both swig 2.0.12 and 3.0.8 我试过swig 2.0.12和3.0.8

Any clue anyone ? 有人知道吗?

I got this to work as you're hoping with SWIG 3.x. 当你希望使用SWIG 3.x时,我得到了这个。 It's definitely overly sensitive here, I think it came down to three things: 它在这里肯定过于敏感,我认为它归结为三件事:

  1. Be consistent with namespaces. 与命名空间保持一致。 Either always use the fully qualified version, or always write everything inside the namespace in the .i file. 要么总是使用完全限定版本,要么总是在.i文件中写入命名空间内的所有内容。
  2. Refer to constructors as Bar instead of Bar::Bar inside %extend . %extend中将构造函数称为Bar而不是Bar::Bar (Per the std::pair example in the documentation ) (根据文档中std::pair示例
  3. Instantiate all your templates before extending any selectively. 在有选择地扩展任何模板之前实例化它们。

I'm not completely sure if all of those things are mandatory, but they certainly were sufficient to make it work here. 我不完全确定所有这些都是强制性的,但它们肯定足以让它在这里起作用。 So my working example looks like: 所以我的工作示例如下:

%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

With test.hh being the C++ code you showed copied verbatim this generates sane Java/JNI. 使用test.hh作为C ++代码,您显示的是逐字复制的,这将生成理智的Java / JNI。

The following would also work too though, following the above guidlines: 根据上述指导原则,以下内容也会有效:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM