要通過這些例子中工作,我創建了下面的頭文件:
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