передача экземпляров классов C++ к Python с повышением:: Python

У меня есть библиотека, которая создает объекты (экземпляры класса 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. В функции количества (и во всех других функциях управления C++) это прекрасный для передачи a как этот или лучше сделать что-то как const shared_ptr<A>&? Во фрагментах кода я нашел в документации повышения Python, ссылка часто используется, но я не понимаю различия (кроме наличия более высокого ссылочного счетчика, конечно).

  2. Действительно ли этот код "Безопасен"? Когда я передам existing_instance Python, его счетчик будет увеличен (только однажды, даже если в Python я сделаю больше копий объекта, конечно), таким образом, нет никакого способа, которым код C++ мог уничтожить объект насколько Python содержит, по крайней мере, "копию". Я корректен? Я пытался играть с указателями, и кажется, что я корректен, я прошу только быть уверенным.

  3. Я хотел бы препятствовать тому, чтобы Python создал экземпляры A. Они должны только быть переданы из кода C++. Как я мог достигнуть этого?Править: найденный, я просто должен использовать no_init и noncopyable: class_<A, boost::noncopyable>("A", no_init)

13
задан UncleZeiv 1 August 2010 в 16:27
поделиться

2 ответа

boost::python knows all about boost::shared_ptr, but you need to tell it that boost:: shared_ptr holds an instance of A, you do this by adding boost::shared_ptr in the template argument list to class_, more information on this 'Held Type' is here in the boost documentation.

To prevent instances being created from python, you add boost::python::no_init to the class_ constructor, so you end up with:

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

In general you should not pass around shared pointers by reference, since if the reference to the shared pointer is invalidated, then the reference to which the shared pointer is pointing to is also invalidated (since taking a reference of the shared pointer didn't increment the reference counter to the pointed to object).

It is perfectly safe to pass boost::shared_ptr objects around to and from python, reference counts (python and shared_ptr) will be correctly managed provided you don't change the return_value_policy. If you change the policy of a method exposed in python so that it returns a reference to a shared pointer then you can cause problems, just as passing shared pointers around by c++ references can cause problems.

(Also, you should use make_shared(...) in preference to shared_ptr(new A(...)).)

14
ответ дан 2 December 2019 в 00:17
поделиться

В этой ситуации мой код будет выглядеть так (для вашего примера):

...

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

Важно запретить boost :: python копировать вещи, но если вы используете shared_ptr скорее всего, вам понадобится копирование только в нескольких контролируемых ситуациях.

1
ответ дан 2 December 2019 в 00:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: