Swig和Python - 不同的对象实例化

时间:2013-03-06 23:09:05

标签: python swig

我有一个关于在Python端生成的swig包装对象和在C ++端生成的包装对象的问题。假设我有以下简单的C ++类定义

#include <vector>

class Sphere
{
public:
    Sphere(){};
};

class Container
{
public:
    Container() : data_(0) {};

    void add() {
        data_.push_back(Sphere());
    }

    Sphere & get(int i) { return data_[i]; }

    std::vector<Sphere> data_;
};

以及以下swig设置

%module engine
%{
#define SWIG_FILE_WITH_INIT
#include "sphere.h"
%}

// -------------------------------------------------------------------------
// Header files that should be parsed by SWIG
// -------------------------------------------------------------------------
%feature("pythonprepend") Sphere::Sphere() %{
    print 'Hello'
%}
%include "sphere.h"

如果我在Python中执行以下操作

import engine
sphere_0 = engine.Sphere()
container = engine.Container()
container.add()
sphere_1 = container.get(0)

然后,包装的Sphere类的第一个实例化会调用Python包装接口的 init 方法(打印出“Hello”)。

然而,在C ++端生成实例的第二个(不打印'Hello')。

由于我的目标是能够在构造对象时添加额外的Python功能,所以我很高兴听到是否有任何人指出正确的方法来实现这一点 - 对于上述两种实例化方案。

致以最诚挚的问候,

的Mads

1 个答案:

答案 0 :(得分:1)

我通常使用接口文件中的显式pythoncode块来执行此类操作:

%pythoncode %{
def _special_python_member_function(self):
     print "hello"
     self.rotate() # some function of Sphere
Sphere.new_functionality=_special_python_member_function
%}

因此,除了SWIG界面提供的功能外,您还可以在类中添加任意python功能。您可能希望/需要rename某些C功能,但这可以为您提供所需的所有成员功能

我从未试图以这种方式重新映射__init__,因此我不知道这会如何表现。假设它不起作用,你将无法确保python对象在构造时具有给定的内部状态(成员变量)。

你将被迫做的是做懒惰的评估:

def function_that_depends_on_python_specific_state(self, *args):
   if not hasatttr( self, 'python_data'):
        self.python_data = self.make_python_data() # construct the relevant data
   pass # do work that involves the python specific data

并检查是否存在python特定数据。如果只有少数情况 对此,我只是把它放在上面的函数中。但是,如果最终成为现实 凌乱,你可以修改__getattr__,以便它构造特定于python的数据 成员,因为他们被访问。

def _sphere_getattr(self, name):
    if name=='python_data':
         self.__dict__[name]=self.make_python_data()
         return self.__dict__[name]
    else:
        raise AttributeError
Sphere.__getattr__ = _sphere_getattr

恕我直言,在你拥有大量新功能的限制以及独立于底层C实现的数据中,你实际上在询问“如何让我的python Sphere类成为C的子类” Sphere类但保持它们的类型相同?“