要通过这些例子中工作,我创建了下面的头文件:
template<typename T>
struct MyTemplateClass
{
bool Validate(T* _in)
{
return false;
}
// ... other stuff... MyTemplateClass is also a container for T*
};
struct Foo {};
的好消息是,它实际上可以生成你要求远远超过你已经尝试什么更简单的代码。我们可以只使用只为Validate
匹配CSOUT类型映射,我们就大功告成了:
%module test
%{
#include "test.hh"
%}
%typemap(csout, excode=SWIGEXCODE) bool Validate {
// referring to _in by name is a bit of a hack here, but it works...
bool ret = _in.swigCMemOwn && $imcall;$excode
return ret;
}
%include "test.hh"
%template(MyTemplateClassInt) MyTemplateClass<int>;
%template(MyTemplateClassFoo) MyTemplateClass<Foo>;
为了完整起见,虽然让我们来看看原来的问题也提出了。首先让我们通过使MyTemplateClass
实际上不是模板来简化事情(即,注释test.hh的第1行,而是在某处添加typedef)。
在这种情况下,你试图做的确实非常多的工作是什么,使用$typemap(cstype, T)
查找在痛饮用于给定类型的C#类型编译的时候:当我们恢复这回是一个
%module test
%{
#include "test.hh"
%}
%typemap(cscode) MyTemplateClass %{
public bool Validate($typemap(cstype, T) in) {
return in.swigCMemOwn && InternalValidate(in);
}
%}
%rename(InternalValidate) Validate;
%include "test.hh"
然而模板再次生成的代码是不正确的,获取生成的Validate
是:
public bool Validate(SWIGTYPE_p_T in)
这是发生,因为夜风(至少3.0,从Ubuntu的14.04)是不知道的大约T t在这方面什么 - 模板替代品离子不能正常发生。我不太确定这是一个错误还是预期的行为,但无论如何这对我们来说都是一个问题。
有趣的是,虽然如果你愿意写一个SWIG看到替代不工作的模板的定义里面的cscode类型映射:
%module test
%{
#include "test.hh"
%}
%rename(InternalValidate) Validate;
template<typename T>
struct MyTemplateClass
{
bool Validate(T* _in)
{
return false;
}
// ... other stuff... MyTemplateClass is also a container for T*
%typemap(cscode) MyTemplateClass %{
public bool Validate($typemap(cstype, T) in) {
return in.swigCMemOwn && InternalValidate(in);
}
%}
};
struct Foo {};
%template(MyTemplateClassInt) MyTemplateClass<int>;
%template(MyTemplateClassFoo) MyTemplateClass<Foo>;
在上面的界面T
类型也得到正确代入输出。所以如果你愿意接受.i文件和你在库中使用的真正头文件之间的重复,那就足够了。你也可以编辑的头文件本身和SWIG和C++混合到的是,以下修改test.hh达到相同的结果:
template<typename T>
struct MyTemplateClass
{
bool Validate(T* _in)
{
return false;
}
// ... other stuff... MyTemplateClass is also a container for T*
#ifdef SWIG
%typemap(cscode) MyTemplateClass %{
public bool Validate($typemap(cstype, T) in) {
return in.swigCMemOwn && InternalValidate(in);
}
%}
#endif
};
struct Foo {};
做是因为夜风定义了预处理宏痛饮,但它不会是在正常的C++编译期间定义,所以一切都很好。就我个人而言,我不喜欢这样 - 我宁愿将C++和SWIG位在逻辑上用一个干净的边界分开。
如果你不愿意重复那样,不能/不会简单地编辑头文件,所有的都不会丢失。我们可以(AB)使用%extend
让我们做同样的事情:
%module test
%{
#include "test.hh"
%}
%rename(InternalValidate) Validate;
%include "test.hh"
%extend MyTemplateClass {
%typemap(cscode) MyTemplateClass %{
public bool Validate($typemap(cstype, T) in) {
return in.swigCMemOwn && InternalValidate(in);
}
%}
}
%template(MyTemplateClassInt) MyTemplateClass<int>;
%template(MyTemplateClassFoo) MyTemplateClass<Foo>;
再次工作。
最后一个解决办法是,如果你已经有了,只是使用T中的模板,如内一个typedef:
template<typename T>
struct MyTemplateClass {
typedef T type;
//...
那么下面的作品,引用类型定义为$1_basetype::type
:
%module test
%{
#include "test.hh"
%}
%rename(InternalValidate) Validate;
%typemap(cscode) MyTemplateClass %{
public bool Validate($typemap(cstype, $1_basetype::type) in) {
return in.swigCMemOwn && InternalValidate(in);
}
%}
%include "test.hh"
%template(MyTemplateClassInt) MyTemplateClass<int>;
%template(MyTemplateClassFoo) MyTemplateClass<Foo>;
所以,尽管看起来应该起作用的简单方式似乎还没有很多选项可以实现我们需要的结果。
感谢您的回答!我会看到最适合我的东西。 – AndyG
如果我采用'%typemap(csout)'的第一种方法,可以说'bool MyTemplateClass :: Validate'吗?我只想为该类匹配该函数(因为我用潜在的多个'bool Validate'函数包装了一个大型代码库)。 – AndyG
要回答我关于'bool MyTemplateClass :: Validate'的问题,它看起来不匹配。 – AndyG