11

Boost.Pythonを使用してC++クラスからPythonモジュールを作成しています。そして、私は参照に関する問題に遭遇しました。

値または参照のいずれかで返すことができるオーバーロードされたgetメソッドを持つクラスFooがある次のケースを考えてみてください。

署名をtypedefすると、値による戻り値を使用するように指定するのは簡単でした。ただし、を使用して参照を返すことも可能であると思います return_value_policy。ただし、適切と思われるものを使用する(doc); return_value_policy<reference_existing_object>うまくいかなかったようです。

私はそれが何をするのか誤解しましたか?

struct Foo {
    Foo(float x) { _x = x; }
    float& get() { return _x; }
    float  get() const { return _x; }
private:
    float _x;
};

// Wrapper code
BOOST_PYTHON_MODULE(my_module)
{
    using namespace boost::python;
    typedef float (Foo::*get_by_value)() const;
    typedef float& (Foo::*get_by_ref)();

    class_<Foo>("Foo", init<float>())
        .def("get", get_by_value(&Foo::get))
        .def("get_ref", get_by_ref(&Foo::get),
            return_value_policy<reference_existing_object>())//Doesn't work
        ;
}

注:生涯管理せずに既存のオブジェクトを参照することは危険である可能性があることを私は知っています。

更新:
オブジェクトでは機能するように見えますが、基本的なデータ型では機能しません。
この改訂された例を見てください:

struct Foo {
    Foo(float x) { _x = x; }
    float& get() { return _x; }
    float  get() const { return _x; }
    void set( float f ){ _x = f;}
    Foo& self(){return *this;}
private:
    float _x;
};

// Wrapper code
using namespace boost::python;
BOOST_PYTHON_MODULE(my_module)
{
    typedef float (Foo::*get_by_value)() const;

    class_<Foo>("Foo", init<float>())
        .def("get", get_by_value(&Foo::get))
        .def("get_self", &Foo::self,
            return_value_policy<reference_existing_object>())
        .def("set", &Foo::set);
        ;
}

テストで期待される結果が得られたのはどれですか?

>>> foo1 = Foo(123)
>>> foo1.get()
123.0
>>> foo2 = foo1.get_self()
>>> foo2.set(1)
>>> foo1.get()
1.0
>>> id(foo1) == id(foo2)
False
4

4 に答える 4

7

Pythonには、不変型の概念があります。不変型はその値を変更できません。組み込みの不変型の例は、int、float、strです。

boost::pythonそうは言っても、 Python自体では関数によって返されるfloatの値を変更できないため、でやりたいことを行うことはできません。

2番目の例は、1つの解決策を示しています。別の例は、シンラッパーを作成してそれを公開することです。

void Foo_set_x(Foo& self, float value) {
    self.get() = value;
}

class_<Foo>("Foo", init<float>())
    ...
    .def("set", &Foo_set_x);
;

これは、元のC++クラスを変更するよりも優れたソリューションです。

于 2010-01-22T18:33:31.603 に答える
3

代わりに内部参照を返したいと思います。私は以前にそれを使って似たようなことをしました。

編集:最新のドキュメント

于 2010-01-05T20:49:08.177 に答える
0

c ++オブジェクトがコピーされていることを確認しますか?毎回新しいpythonオブジェクトを取得しますが、これは同じc++オブジェクトを参照します。オブジェクトがコピーされたことをどのように判断していますか?

于 2009-10-15T10:07:14.140 に答える
0

Boost.Pythonについてはよくわからないので、質問を誤解する可能性があります。その場合、これはまったく役に立ちません。しかし、ここに行きます:

Pythonでは、参照または値のどちらで返すかを選択できません。Pythonではこの区別は意味がありません。すべてが参照によって処理されていると考えるのが最も簡単だと思います。

オブジェクトがあり、それらのオブジェクトの名前があります。それで

foo = "ryiuy"

文字列オブジェクト「ryiuy」を作成し、その文字列オブジェクトを「foo」という名前で参照できるようにします。したがって、Pythonでは、何かが渡されると、そのオブジェクトが渡されます。そのような「値」はないので、値を渡すことはできません。しかし、繰り返しになりますが、参照も存在せず、オブジェクトとその名前だけが存在することも有効な視点です。

したがって、答えは、Cで参照を取得するときに、参照をPythonに参照するオブジェクトへの参照を渡す必要があるということです。また、Cで値を取得するときは、その値から作成したオブジェクトへの参照をPythonに渡す必要があります。

于 2009-10-15T09:04:48.930 に答える