2014-03-12 48 views
3

我正在使用SWIG來封裝C++代碼以便在Python測試框架中使用。我的問題是,我得到一個指向我需要調用方法的類的實例的指針。例如,我痛飲文件example.i內:如何使用swig包裝器調用C++類指針的方法?

iExample* getMyClassInstance(); 

... 

class iExample 
{ 
    public: 
     virtual void somePureVirtualMethod() = 0; 
// ... 
}; 

現在,蟒蛇,如果我有課,我可以調用該方法

myClassInstance.somePureVirtualMethod() 

不過,我實際上沒有一個當然,這個班的實例。我有一個由SWIG生成的不透明指針。我如何使用它?顯然,在Python,我不能做

myClassInstancePtr = example.getMyClassInstance() 
myClassInstancePtr->somePureVirtualMethod() 

我嘗試使用cpointer.i或pointer.i在痛飲產生指針的功能,但是這是沒有好,因爲它試圖創建類的副本。這甚至不能使用純虛擬方法編譯接口,即使我沒有使用純虛擬方法,我也不想創建該類的副本,我只想調用它的一些東西!

回答

2

SWIG可以處理這種情況。確保你在SWIG中定義了接口,然後它不會是不透明的。這裏有一個工作示例:

%module x 

%inline %{ 

// Define the interface. 
struct iExample 
{ 
    virtual int somePureVirtualMethod() = 0; 
}; 

iExample* getMyClassInstance(); 

%} 

// Implementation, not exposed to Python 
%{ 
struct Internal : public iExample 
{ 
    int somePureVirtualMethod() { return 5; } 
}; 
iExample* getMyClassInstance() { return new Internal(); } 
%} 

演示:

>>> import x 
>>> i = x.getMyClassInstance() 
>>> i.somePureVirtualMethod() 
5 

然而,這種實現將泄漏的內部實例。您可能想要實現一種自動釋放它的方法。一種方法是使用%newobject並定義一個虛擬析構函數。當沒有更多引用時,Python將刪除該對象。

%module x 

%newobject getMyClassInstance; 

%inline %{ 
struct iExample 
{ 
    virtual ~iExample() {}; 
    virtual int somePureVirtualMethod() = 0; 
}; 
iExample* getMyClassInstance(); 
%} 

// Implementation 
%{ 
#include <iostream> 
struct Internal : public iExample 
{ 
    int somePureVirtualMethod() { return 5; } 
    ~Internal() { std::cout << "destroyed" << std::endl; } 
}; 
iExample* getMyClassInstance() { return new Internal(); } 
%} 

演示:

>>> import x 
>>> i = x.getMyClassInstance() 
>>> i.somePureVirtualMethod() 
5 
>>> i=2  # reassign i 
destroyed  # garbage-collected 
+1

+1很好解釋。但是,SWIG的新手可能不知道如何使用%inline創建獨立.i(可能從一行評論中受益)。 – Schollii

+0

對,我沒有意識到''。可以調用Swigged C到Python代碼中指針的方法。測試它,它的工作原理。如果你需要一個明確的順從,我的答案會做,但如果你只是想調用指針上的方法,假裝指針是一個引用,並使用'。'。 – m24p

1

我發現的最簡單的答案是編輯你的example.i,添加一些輔助函數來解引用。在你痛飲文件example.i:

{% 
... 
// Helper function to dereference pointers within python 
template <typename T> 
T& dereference(T* ptr) 
{ 
    return *ptr; 
} 
... 
%} 
... 
// Make every version of the templated functions we'll need 
template <typename T> T& dereference(T* ptr); 
%template(dereferencePtr_iExample) dereference<iExample>; 
在Python

現在

myClassInstance = example.dereferencePtr_iExample(example.getMyClassInstance()) 
myClassInstance.somePureVirtualMethod() 

我想這個方法應該一般工作像perl的其他語言,你不必耍着SWIG類型圖。

+0

我不明白你爲什麼要提領。解引用是一個特定於指針的C++概念,Python對指針,只有引用一無所知,所以SWIG已經爲你處理這個問題。爲什麼Mark的解決方案不夠?他也不使用模板。 – Schollii

+0

我還沒有看過Mark的解決方案。那是週末。除了工作之外,我有一個家庭和愛好。我將在本週查看它,我今天一直在進行其他調試。而模板只是一個乾淨的通用解決方案。我最初的解決方案沒有使用模板。模板有問題嗎? – m24p