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:
この単純な継承構造を見てみましょう.
And a set of C++ functions operating on
これらのBaseクラスとDerivedクラスのオブジェクトを操作するc++関数もあります.
We've seen how we can wrap the base class
次に、ベースクラスをカプセル化する方法を示します.
Now we can inform Boost.Python of the inheritance relationship between
boost.に伝えることができますpython DerivedクラスとそのベースクラスBaseとの間の継承関係.したがって、次のようになります.
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,
これを行うと、追加の効果が得られます.
1. DerivedクラスはBaseクラスのpythonメソッド(パッケージのc++メンバー関数)を自動的に継承します.
2. Baseがマルチステートである場合、ポインタまたはリファレンスによってPythonに渡されるDerivedオブジェクトは、ポインタまたはリファレンスでDerivedオブジェクトをパラメータとして必要とする場所に渡すこともできます.
Now, we will expose the C++ free functions
c++関数b,d,factoryを暴露します.
Note that free function
なお、自由関数factoryは、Derivedクラスのオブジェクトを作成するために使用される.これらの例ではreturn_を使用しますvalue_policyは、PythonにBaseのポインタを受信するように伝え、PythonのBaseオブジェクト(すなわち、パッケージされたPythonのBaseクラス、および以前のC++のBaseクラスはクラスではない)にこのインスタンスを保存し、このPythonペアが破棄されるまで保存します.Boost.Pythonのcall policiesでは、より多くの関連情報が表示されます.
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
この部分では,虚関数による多態性の実現方法を学習する.我々の例を継承し、ベースクラスに虚関数を追加します.
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
Boost.Pythonの目標の一つは,現在あるc++設計への変更を最小限に抑えることである.原則として、サードパーティのライブラリにインタフェースを提供する際に、既存の設計を変更しないようにする必要があります.Baseクラスにコードを追加するのは望ましくありません.また、Pythonで書き換えられ、C++からマルチステートの虚関数を使用する場合は、プログラムの正常な動作を保証するために補助コードを追加する必要があります.私たちがしなければならないのはBaseから新しいクラス(PS:通常は最後のクラス、例えばAがベースクラス、BがAを継承し、Aを継承してカプセル化すると、クラスBのオブジェクトに変えることはできない)を継承し、カプセル化することです.これにより、修正せずに虚関数にフックを追加し、Pythonで関数を書き換えた後も呼び出すことができます.
Notice too that in addition to inheriting from
ベースクラスから継承すると同時に多重継承されることに注意
(詳しくはWrapperを参照
).このwrapper templateはクラスをカプセル化し,言い換えればPythonで虚関数を書き換えるのがより簡単になる.
PS:例ではclassではなくstructを用いる.直接classに変更すると、「BaseWrapからwrapper への変換は存在するが、アクセスできない」ため、classを使用するには次のように書く必要があります.
MSVC6/7 Workaround
If you are using Microsoft Visual C++ 6 or 7, you have to write
Microsoft Visual C++6 or 7を使用する場合は、f関数をこのように書く必要があります.
BaseWrap's overridden virtual member function
BaseWrap書き換えの虚関数fは実行時にget_を通過するoverride(...)該当するPythonオブジェクトを呼び出す方法.
Finally, exposing
最後に、ベースを暴露:
pure_virtual記号はBoost.に伝えます.Python関数fは純虚関数である.
ノート注意
メンバー関数法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クラスをカプセル化した.ベースクラス:
had a pure virtual function
純粋な虚関数fがある.ただし、メンバー関数fが純虚関数として宣言されていない場合は、
We wrap it this way:
このようにカプセル化します.
Notice how we implemented
どうやって実現するかに注意してください
. 関数fの書き換えがあるかどうかを確認しなければなりません.もしそうでなければ、
MSVC6/7 Workaround
If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line with the
Microsoft Visual C++6 or 7を使用する場合は、「*note*」のある行を次のように置き換える必要があります.
Finally, exposing:
最後に、インタフェースを提供します.
Take note that we expose both
In Python, the results would be as expected:
Pythonでは、結果は次のようになります.
Calling
Calling
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
// 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 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は純虚関数である.
ノート注意
メンバー関数法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