在模板中包装 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 实现了这一点。这里绝对是过于敏感了,我认为归结为三点:
- 与名称空间保持一致。要么始终使用完全限定版本,要么始终将所有内容写入 .i 文件中的命名空间。
- 在
%extend
中将构造函数称为 Bar
而不是 Bar::Bar
。 (根据 std::pair
example in the documentation)
- 在有选择地扩展任何模板之前实例化所有模板。
我不完全确定是否所有这些都是强制性的,但它们肯定足以让它在这里发挥作用。所以我的工作示例如下所示:
%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>;
};
我有一个复杂的 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 实现了这一点。这里绝对是过于敏感了,我认为归结为三点:
- 与名称空间保持一致。要么始终使用完全限定版本,要么始终将所有内容写入 .i 文件中的命名空间。
- 在
%extend
中将构造函数称为Bar
而不是Bar::Bar
。 (根据std::pair
example in the documentation) - 在有选择地扩展任何模板之前实例化所有模板。
我不完全确定是否所有这些都是强制性的,但它们肯定足以让它在这里发挥作用。所以我的工作示例如下所示:
%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>;
};