Reputation: 559
I have a complex c++ library that I need to expose to a java android application. This C++ library consists of standard C++ classes and C++ class templates.
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:
%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. I.e. the BBar
java class looks like this:
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.
I have tried with both swig 2.0.12 and 3.0.8
Any clue anyone ?
Upvotes: 4
Views: 573
Reputation: 88711
I got this to work as you're hoping with SWIG 3.x. It's definitely overly sensitive here, I think it came down to three things:
Bar
instead of Bar::Bar
inside %extend
. (Per the std::pair
example in the documentation)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.
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>;
};
Upvotes: 1