假设您有一个模板类Foo
,并且您希望透明地使用Swig包装它,以便您可以打印该类:
>>> from example import *
>>> f = Foo2()
>>> print(f)
In Foo class!
我已关注this post和this one。所以我的头文件是:
#include <iostream>
template <int d> class Foo {
public:
friend std::ostream &operator<<(std::ostream &os, const Foo &m) {
os << "Inside Foo class!" << std::endl;
return os;
}
};
我的界面文件:
%{
#include <sstream>
#include <iostream>
#include "foo.hpp"
%}
%include "std_iostream.i"
// Try grabbing it unmodified
%include "foo.hpp"
/* Instantiate a few different versions of the template */
%template(Foo2) Foo<2>;
%template(Foo3) Foo<3>;
%extend Foo<2> {
const char *__str__() {
std::ostringstream oss(std::ostringstream::out);
oss << *self;
return oss.str().c_str();
}
};
所以这很好用,我可以像以前一样打印对象,但是我想将它概括为模板参数的任何值,因为复制每个模板参数的代码都没有意义。我在界面文件中尝试了以下操作,但它没有工作:
template <int d> class Foo {
public:
%extend {
const char *__str__() {
std::ostringstream oss(std::ostringstream::out);
oss << *self;
return oss.str().c_str();
}
}
};
答案 0 :(得分:3)
您可以通过省略模板参数列表,从其定义之外%extend
%extend Foo {
const char *__str__() {
std::ostringstream oss(std::ostringstream::out);
oss << *self;
return oss.str().c_str();
}
};
%template(Foo2) Foo<2>;
%template(Foo3) Foo<3>;
主模板:
%define WRAP_FOO(N)
%template( Foo ## N ) Foo<N>;
%extend Foo<N> {
const char *__str__() {
std::ostringstream oss(std::ostringstream::out);
oss << *self;
return oss.str().c_str();
}
};
%enddef
/* Instantiate a few different versions of the template */
WRAP_FOO(2)
WRAP_FOO(3)
或者您可以使用SWIG宏一次性包装和扩展每个专业化:
.c_str()
请注意,在任何一种情况下,您都会通过返回在函数返回之前销毁的std::string
的{{1}}结果来导致未定义的行为。
答案 1 :(得分:1)
您在最后一个示例中使用的%extend
语法应该是正确的,这是我们在OpenStudio中使用的一种技术
我认为问题在于您定义模板2次,一次在%import
指令中,一次在.i
文件中。第一个定义是SWIG正在使用的定义。
虽然不理想,但我相信您需要删除%include "foo.hpp"
指令并明确定义所需的接口。您的新.i
文件现在变为:
%{
#include <sstream>
#include <iostream>
#include "foo.hpp"
%}
%include "std_iostream.i"
// Don't let SWIG directly parse foo.hpp
// %include "foo.hpp"
template <int d> class Foo {
public:
// include here prototypes for all functions
// you want exposed. You don't need the implementation like in
// a normal C++ template declaration
// include here any extensions you want to add
%extend {
const char *__str__() {
std::ostringstream oss(std::ostringstream::out);
oss << *self;
return oss.str().c_str();
}
}
};
/* Instantiate a few different versions of the template */
%template(Foo2) Foo<2>;
%template(Foo3) Foo<3>;
或者,您可以直接将SWIG代码放在hpp文件中,而不必维护两个API:
新的.i文件:
%{
#include <sstream>
#include <iostream>
#include "foo.hpp"
%}
%include "std_iostream.i"
// let swig directly parse foo.hpp
%include "foo.hpp"
/* Instantiate a few different versions of the template */
%template(Foo2) Foo<2>;
%template(Foo3) Foo<3>;
新的.hpp文件:
#include <iostream>
template <int d> class Foo {
public:
#ifdef SWIG
%extend {
const char *__str__() {
std::ostringstream oss(std::ostringstream::out);
oss << *self;
return oss.str().c_str();
}
}
#endif
friend std::ostream &operator<<(std::ostream &os, const Foo &m) {
os << "Inside Foo class!" << std::endl;
return os;
}
};