如何使用swig包装器调用C ++类指针上的方法?

时间:2014-03-12 20:39:02

标签: python c++ swig

我使用SWIG来包装C ++代码以便在Python测试框架中使用。我的问题是我得到一个指向类实例的指针,然后我需要调用方法。例如,在我的swig文件example.i中:

iExample* getMyClassInstance();

...

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

现在,在python中,如果我有类,我可以调用方法

myClassInstance.somePureVirtualMethod()

但是,当然,我实际上并没有这个班级的实例。我有一个从SWIG生成的不透明指针。我该如何使用它?显然在Python中我无法做到

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

我尝试在swig中使用cpointer.i或pointer.i来生成指针函数,但这并不好,因为它试图创建类的副本。这甚至不能用纯虚方法的接口编译,即使我没有使用纯虚方法,我也不想创建类的副本,我只想调用它上面的东西!

2 个答案:

答案 0 :(得分: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)

我发现最简单的答案是编辑你的example.i以添加一些辅助函数来进行解除引用。在您的swig文件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类型图。