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++ 側で生成される 2 番目のインスタンスは生成されません ('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 機能を追加できます。C の機能の一部を途中で使用したい/必要とする場合がありますrenameが、これにより、必要なすべてのメンバー関数を取得できます。

この方法で再マップしようとしたこと__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 に答える