2014-03-12 4 views
3

저는 SWIG를 사용하여 Python 테스트 프레임 워크 내에서 C++ 코드를 랩핑했습니다. 내 문제는 내가 다음 메서드를 호출하는 데 필요한 클래스의 인스턴스에 대한 포인터를 얻고있다. 예, 내 꿀꺽 꿀꺽 파일 본보기 내 : I 클래스가 있다면swig 래퍼를 사용하여 C++ 클래스 포인터에서 메소드를 호출하려면 어떻게해야합니까?

iExample* getMyClassInstance(); 

... 

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

지금, 파이썬에서, 난 그냥 그러나 방법을

myClassInstance.somePureVirtualMethod() 

를 부를 수, 나는 실제로이없는 클래스의 인스턴스. SWIG에서 생성 된 불투명 포인터가 있습니다. 어떻게 사용합니까? 물론 파이썬에서 나는 포인터 기능을 생성하기 위해 한모금에 cpointer.i 또는 pointer.i를 사용하여 시도

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

할 수는 없지만,이 클래스의 사본을 만들려고 있기 때문에 즉, 좋은 없습니다. 순수 가상 메서드가있는 인터페이스로도 컴파일 할 수 없으며 순수 가상 메서드를 사용하지 않아도 클래스 복사본을 만들고 싶지는 않습니다.

답변

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을 사용하고 가상 소멸자를 정의하는 것입니다. 파이썬은 더 이상 객체에 대한 참조가 없을 때 객체를 삭제합니다.

%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에서 파이썬 코드로 포인터에 대한 메소드를 호출 할 수 있습니다. 그것을 테스트하고 작동합니다. 명시 적 추론이 필요한 경우 내 대답을 그것을 할 것이다,하지만 포인터에 대한 메서드를 호출하려면 포인터가 참조 인 척하고 '.'사용하십시오. – m24p

1

가장 간단한 답은 example.i를 편집하여 역 참조를 수행하는 도우미 함수를 추가하는 것입니다. 당신 꿀꺽 꿀꺽 파일 본보기에서 :

나는이 방법뿐만 아니라 펄 같은 다른 언어에 대한 일반적으로 작동합니다 상상, 그리고 당신이 주변에 나사 필요가 없습니다

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

파이썬에서 이제

{% 
... 
// 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>; 

SWIG typemaps.

+0

당신은 역 참조에 필요한 이유를 이해하지 않습니다. Dereferencing은 포인터에 대한 C++ 개념이며, 파이썬은 포인터에 대해서는 아무것도 알지 못하므로 참조 만하므로 SWIG는 이미이를 처리합니다. Mark의 솔루션이 적절한 이유는 무엇입니까? 그도 템플릿을 사용하지 않습니다. – Schollii

+0

아직 마크의 해결책을 보지 못했습니다. 주말 이었어. 나는 가족과 취미가 직장 밖에서. 나는 이번 주에 그것을 점검 할 것이고, 나는 다른 디버깅을 위해 오늘 일하고있다. 템플릿은 깨끗하고 일반적인 솔루션을위한 것입니다. 내 초기 솔루션은 템플릿을 사용하지 않았습니다. 템플릿에 문제가 있습니까? – m24p

관련 문제