14

オブジェクト(クラスAのインスタンス)を作成し、それらのメソッドを呼び出すことができるPythonプログラムにそれらを渡すライブラリがあります。

基本的に私はC++クラスのインスタンスを持っており、Pythonからそれらを使用したいと思います。場合によっては、そのオブジェクトを操作のためにC++に戻す必要があります。

New次のラッパーファイルを作成しました(関数がC ++コードのどこかで呼び出されていると仮定します)。

#include <boost/python.hpp>
#include <iostream>
#include <boost/smart_ptr.hpp>

using namespace boost;
using namespace boost::python;

int calls = 0;

struct A
{
   int f() { return calls++; }
   ~A() { std::cout << "destroyed\n"; }
};

shared_ptr<A> existing_instance;

void New() { existing_instance = shared_ptr<A>( new A() ); }

int Count( shared_ptr<A> a ) { return a.use_count(); }

BOOST_PYTHON_MODULE(libp)
{
    class_<A>("A")
        .def("f", &A::f)
    ;

    def("Count", &Count);

    register_ptr_to_python< shared_ptr<A> >();
} 

このコードには、Pythonが。を取得する部分がありませんexisting_instance。私はそれを貼り付けませんでしたが、その目的のためにコールバックメカニズムを使用するとしましょう。

このコードは機能しますが、いくつか質問があります。

  1. Count関数(および他のすべてのC ++操作関数)では、aそのように渡すのは問題ありませんか、それとも次のようなことを行う方が良いconst shared_ptr<A>&ですか?Python Boostのドキュメントで見つけたコードスニペットでは、参照がよく使用されますが、違いがわかりません(もちろん、より高い参照カウンターがあることを除けば)。

  2. このコードは「安全」ですか?既存のインスタンスをpythonに渡すと、そのカウンターがインクリメントされます(Pythonでオブジェクトのコピーをさらに作成する場合でも、もちろん1回だけです)。そのため、Pythonが保持している限り、C++コードがオブジェクトを破棄することはできません。少なくとも「コピー」。私は正しいですか?ポインタで遊んでみましたが、正解のようです。念のためお願いします。

  3. PythonがAのインスタンスを作成しないようにしたいのですが、C++コードからのみ渡す必要があります。どうすればそれを達成できますか?編集:見つかりました、私はno_initとコピー不可を使用する必要があります:class_<A, boost::noncopyable>("A", no_init)

4

2 に答える 2

14

boost::pythonについてはすべて知っていますが、のインスタンスboost::shared_ptrを保持していることを伝える必要があります。これを行うには、テンプレート引数リストをに追加します。この「保持タイプ」の詳細については、ブーストドキュメントを参照してくださいboost::shared_ptr<A>Aboost::shared_ptr<A>class_

インスタンスがPythonから作成されないようにするboost::python::no_initには、class_コンストラクターに追加するため、最終的に次のようになります。

boost::python::class_< A, boost::shared_ptr<A> >("A", boost::python::no_init)
    //... .def, etc
    ;

一般に、共有ポインターへの参照が無効になると、共有ポインターが指している参照も無効になるため、参照によって共有ポインターを渡すことはできません(共有ポインターの参照を取得しても増分されなかったため)ポイントされたオブジェクトへの参照カウンター)。

pythonとの間でオブジェクトを渡すことは完全に安全です。boost::shared_ptrを変更しない限り、参照カウント(pythonおよびshared_ptr)は正しく管理されますreturn_value_policy。Pythonで公開されているメソッドのポリシーを変更して、共有ポインターへの参照を返すようにすると、c ++参照によって共有ポインターを渡すと問題が発生するのと同じように、問題が発生する可能性があります。

(また、をmake_shared<A>(...)優先して使用する必要がありますshared_ptr<A>(new A(...))。)

于 2010-07-31T13:00:49.323 に答える
1

この状況では、私のコードは次のようになります(あなたの例では):

...

BOOST_PYTHON_MODULE(libp)
{
    class_<A, boost::shared_ptr<A>, boost::noncopyable >("A")
       .def("f", &A::f)
       .def("Count", &Count)
     ;
 } 

物事をコピーするためにboost::pythonを禁止することは重要ですが、shared_ptrを使用している場合は、いくつかの制御された状況でのみコピーする必要がある可能性があります。

于 2010-07-27T13:21:48.153 に答える