简体   繁体   English

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

[英]How do I invoke a method on a C++ class pointer with swig wrappers?

I'm using SWIG to wrap C++ code for use within a Python testing framework. 我正在使用SWIG来包装C ++代码,以便在Python测试框架中使用。 My problem is that I'm getting a pointer to an instance of a class that I need to then invoke methods on. 我的问题是我得到一个指向类的实例的指针,然后我需要调用方法。 Eg, within my swig file example.i: 例如,在我的swig文件example.i中:

iExample* getMyClassInstance();

...

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

Now, in python, if I had the class, I could just call the method 现在,在python中,如果我有类,我可以调用该方法

myClassInstance.somePureVirtualMethod()

However, I don't actually have an instance of the class, of course. 但是,我当然没有该类的实例。 I have an opaque pointer generated from SWIG. 我有一个从SWIG生成的不透明指针。 How do I use it? 我该如何使用它? Obviously in Python I can't do 显然在Python中我无法做到

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

I tried using cpointer.i or pointer.i in swig to generate pointer functions, but that's no good, because it's trying to create copies of the class. 我尝试在swig中使用cpointer.i或pointer.i来生成指针函数,但这并不好,因为它正在尝试创建类的副本。 This can't even compile with an interface with pure virtual methods, and even if I wasn't using pure virtual methods, I don't want to create a copy of the class, I just want to invoke something on it! 这甚至无法使用纯虚方法的接口进行编译,即使我没有使用纯虚方法,我也不想创建类的副本,我只想在其上调用一些东西!

SWIG can handle this just fine. SWIG可以处理这个问题。 Make sure you define the interface in SWIG and then it won't be opaque. 确保在SWIG中定义界面,然后它不会是不透明的。 Here's a working example: 这是一个有效的例子:

%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(); }
%}

Demo: 演示:

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

However, this implementation will leak an Internal Instance. 但是,此实现将泄漏内部实例。 You may want to implement a way to free it automatically. 您可能希望实现一种自动释放它的方法。 One way is to use %newobject and define a virtual destructor. 一种方法是使用%newobject并定义虚拟析构函数。 Python will delete the object when there are no more references to it. 当没有对象的引用时,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(); }
%}

Demo: 演示:

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

The simplest answer I've found is to edit your example.i to add in some helper functions to do dereferencing. 我发现最简单的答案是编辑你的example.i以添加一些辅助函数来进行解除引用。 In your swig file 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>;

Now in python 现在在python中

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

I imagine this method should work generically for other languages like perl as well, and you don't have to screw around with SWIG typemaps. 我想这种方法一般也适用于perl等其他语言,而且你不必使用SWIG类型图。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM