boost.python--継承


公式サイトの文を本として、できるだけ翻訳して、後で見るのに便利です.私が使っているboostバージョンは1.5です.1 .許しサイト:http://www.boost.org/doc/libs/1_51_0/libs/python/doc/tutorial/doc/html/python/exposing.html#python.inheritance
Inheritance
継承
In the previous examples, we dealt with classes that are not polymorphic. This is not often the case. Much of the time, we will be wrapping polymorphic classes and class hierarchies related by inheritance. We will often have to write Boost.Python wrappers for classes that are derived from abstract base classes.
前の例では,我々が処理するクラスは多態性を備えておらず,実際の状況では多くない.多くの場合、マルチステートクラスとクラスの継承関係をパッケージします.私たちもよくboost.を使います.pythonは、絶虚ベースクラスから継承されたクラスをパッケージします.
Consider this trivial inheritance structure:
この単純な継承構造を見てみましょう.
struct Base { virtual ~Base(); };
struct Derived : Base {};

And a set of C++ functions operating on  Base  and  Derived  object instances:
これらのBaseクラスとDerivedクラスのオブジェクトを操作するc++関数もあります.
void b(Base*);
void d(Derived*);
Base* factory() { return new Derived; }

We've seen how we can wrap the base class  Base :
次に、ベースクラスをカプセル化する方法を示します.
class_<Base>("Base")
    /*...*/
    ;

Now we can inform Boost.Python of the inheritance relationship between  Derived  and its base class  Base . Thus:
boost.に伝えることができますpython DerivedクラスとそのベースクラスBaseとの間の継承関係.したがって、次のようになります.
class_<Derived, bases<Base> >("Derived")
    /*...*/
    ;

Doing so, we get some things for free:
Derived automatically inherits all of Base's Python methods (wrapped C++ member functions)
If Base is polymorphic,  Derived  objects which have been passed to Python via a pointer or reference to  Base  can be passed where a pointer or reference to  Derived  is expected.
これを行うと、追加の効果が得られます.
  1. DerivedクラスはBaseクラスのpythonメソッド(パッケージのc++メンバー関数)を自動的に継承します.
  2. Baseがマルチステートである場合、ポインタまたはリファレンスによってPythonに渡されるDerivedオブジェクトは、ポインタまたはリファレンスでDerivedオブジェクトをパラメータとして必要とする場所に渡すこともできます.
Now, we will expose the C++ free functions  b  and  d  and  factory :
c++関数b,d,factoryを暴露します.
def("b", b);
def("d", d);
def("factory", factory);

Note that free function  factory  is being used to generate new instances of class  Derived . In such cases, we use return_value_policy<manage_new_object>  to instruct Python to adopt the pointer to  Base  and hold the instance in a new Python  Base object until the the Python object is destroyed. We will see more of Boost.Python call policies later.
なお、自由関数factoryは、Derivedクラスのオブジェクトを作成するために使用される.これらの例ではreturn_を使用しますvalue_policyは、PythonにBaseのポインタを受信するように伝え、PythonのBaseオブジェクト(すなわち、パッケージされたPythonのBaseクラス、および以前のC++のBaseクラスはクラスではない)にこのインスタンスを保存し、このPythonペアが破棄されるまで保存します.Boost.Pythonのcall policiesでは、より多くの関連情報が表示されます.
// Tell Python to take ownership of factory's result
def("factory", factory,
    return_value_policy<manage_new_object>());

Class Virtual Functions
クラス虚関数
In this section, we will learn how to make functions behave polymorphically through virtual functions. Continuing our example, let us add a virtual function to our  Base  class:
この部分では,虚関数による多態性の実現方法を学習する.我々の例を継承し、ベースクラスに虚関数を追加します.
struct Base
{
    virtual ~Base() {}
    virtual int f() = 0;
};

One of the goals of Boost.Python is to be minimally intrusive on an existing C++ design. In principle, it should be possible to expose the interface for a 3rd party library without changing it. It is not ideal to add anything to our class  Base . Yet, when you have a virtual function that's going to be overridden in Python and called polymorphically from C++, we'll need to add some scaffoldings to make things work properly. What we'll do is write a class wrapper that derives from  Base  that will unintrusively hook into the virtual functions so that a Python override may be called:
Boost.Pythonの目標の一つは,現在あるc++設計への変更を最小限に抑えることである.原則として、サードパーティのライブラリにインタフェースを提供する際に、既存の設計を変更しないようにする必要があります.Baseクラスにコードを追加するのは望ましくありません.また、Pythonで書き換えられ、C++からマルチステートの虚関数を使用する場合は、プログラムの正常な動作を保証するために補助コードを追加する必要があります.私たちがしなければならないのはBaseから新しいクラス(PS:通常は最後のクラス、例えばAがベースクラス、BがAを継承し、Aを継承してカプセル化すると、クラスBのオブジェクトに変えることはできない)を継承し、カプセル化することです.これにより、修正せずに虚関数にフックを追加し、Pythonで関数を書き換えた後も呼び出すことができます.
struct BaseWrap : Base, wrapper<Base>
{
    int f()
    {
        return this->get_override("f")();
    }
};

Notice too that in addition to inheriting from  Base , we also multiply- inherited  wrapper<Base>  (See Wrapper). The  wrapper  template makes the job of wrapping classes that are meant to overridden in Python, easier.
ベースクラスから継承すると同時に多重継承されることに注意wrapper<Base>
(詳しくはWrapperを参照
).このwrapper templateはクラスをカプセル化し,言い換えればPythonで虚関数を書き換えるのがより簡単になる.
PS:例ではclassではなくstructを用いる.直接classに変更すると、「BaseWrapからwrapperへの変換は存在するが、アクセスできない」ため、classを使用するには次のように書く必要があります.
class BaseWrap : public Base, public wrapper<Base> {...};

 MSVC6/7 Workaround
If you are using Microsoft Visual C++ 6 or 7, you have to write  f  as:
Microsoft Visual C++6 or 7を使用する場合は、f関数をこのように書く必要があります.return call<int>(this->get_override("f").ptr()); .
BaseWrap's overridden virtual member function  f  in effect calls the corresponding method of the Python object through  get_override .
BaseWrap書き換えの虚関数fは実行時にget_を通過するoverride(...)該当するPythonオブジェクトを呼び出す方法.
Finally, exposing  Base :
最後に、ベースを暴露:
class_<BaseWrap, boost::noncopyable>("Base")
    .def("f", pure_virtual(&Base::f))
    ;
pure_virtual  signals Boost.Python that the function  f  is a pure virtual function.
pure_virtual記号はBoost.に伝えます.Python関数fは純虚関数である.
[Note]
ノート注意
メンバー関数法Python,like many object oriented languages uses the term methods.Methods correspond roughly to C++'s member functions Pythonは、多くのオブジェクト言語に直面する使用方法のように、c++ではメンバー関数と呼ばれています.
Virtual Functions with Default Implementations
デフォルト実装の虚関数
We've seen in the previous section how classes with pure virtual functions are wrapped using Boost.Python's class wrapper facilities. If we wish to wrap non-pure-virtual functions instead, the mechanism is a bit different.
前の章では、Boostの使い方を学びました.Pythonクラスwrapperツールは純虚関数をカプセル化する.非純虚関数をカプセル化したい場合,この動作機構は少し異なる.
Recall that in the previous section, we wrapped a class with a pure virtual function that we then implemented in C++, or Python classes derived from it. Our base class:
以前の章では,純粋な虚関数を持つc++クラス,またはそのPythonクラスをカプセル化した.ベースクラス:
struct Base
{
    virtual int f() = 0;
};

had a pure virtual function  f . If, however, its member function  f  was not declared as pure virtual:
純粋な虚関数fがある.ただし、メンバー関数fが純虚関数として宣言されていない場合は、
struct Base
{
    virtual ~Base() {}
    virtual int f() { return 0; }
};

We wrap it this way:
このようにカプセル化します.
struct BaseWrap : Base, wrapper<Base>
{
    int f()
    {
        if (override f = this->get_override("f"))
            return f(); // *note*
        return Base::f();
    }

    int default_f() { return this->Base::f(); }
};

Notice how we implemented  BaseWrap::f . Now, we have to check if there is an override for  f . If none, then we call  Base::f() .
どうやって実現するかに注意してくださいBaseWrap::f
. 関数fの書き換えがあるかどうかを確認しなければなりません.もしそうでなければ、Base::f()を呼び出します.
 MSVC6/7 Workaround
If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line with the  *note*  as:
Microsoft Visual C++6 or 7を使用する場合は、「*note*」のある行を次のように置き換える必要があります.return call<char const*>(f.ptr()); .
Finally, exposing:
最後に、インタフェースを提供します.
class_<BaseWrap, boost::noncopyable>("Base")
    .def("f", &Base::f, &BaseWrap::default_f)
    ;

Take note that we expose both  &Base::f  and  &BaseWrap::default_f . Boost.Python needs to keep track of 1) the dispatch function  f  and 2) the forwarding function to its default implementation  default_f . There's a special  def  function for this purpose. &Base::f and &BaseWrap::default_f を同時に暴露したことに注意してください. Boost.Pythonは1)スケジューリング関数f 2)そのデフォルト実装の関数default_を追跡する必要があるf .この目的を達成するために,ここには特殊なdef関数がある.
In Python, the results would be as expected:
Pythonでは、結果は次のようになります.
>>> base = Base()
>>> class Derived(Base):
...     def f(self):
...         return 42
...
>>> derived = Derived()

Calling  base.f() :
>>> base.f()
0

Calling  derived.f() :
>>> derived.f()
42