1

我有一个关于在 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 功能,因此我很高兴听到是否有人对实现这一目标的正确方法有任何指示 - 对于上述两种实例化场景。

最好的祝福,

麦兹

4

1 回答 1

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 类的子类但是让它们保持同一类型?”

于 2013-03-06T23:52:37.383 回答