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

  2. Является ли этот код «безопасным»? Когда я передаю существующий_инстамент на python, его счетчик будет увеличиваться (только один раз, даже если в python я делаю больше копий объекта, конечно), поэтому нет никакого способа, чтобы код C ++ мог уничтожить объект, поскольку python имеет место по крайней мере, «копией». Я прав? Я пытался играть с указателями, и, похоже, я прав, я просто хочу быть уверенным.

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

2 Solutions collect form web for “передача экземпляров классов C ++ в python с boost :: python”

boost::python знает все о boost::shared_ptr , но вам нужно сказать, что boost::shared_ptr<A> содержит экземпляр A , вы делаете это, добавляя boost::shared_ptr<A> в список аргументов шаблона, чтобы class_ , более подробная информация об этом «Held Type» приведена в документации по ускорению .

Чтобы предотвратить создание экземпляров из python, вы добавляете boost::python::no_init в конструктор class_, поэтому в итоге вы получаете:

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

В общем случае вы не должны передавать общие указатели по ссылке, так как если ссылка на общий указатель недействительна, то ссылка, на которую указывает указатель общего указателя, также недействительна (поскольку использование ссылки общего указателя не увеличилось контрольный счетчик к указанному объекту).

Совершенно безопасно передавать объекты boost::shared_ptr вокруг и из python, количество ссылок (python и shared_ptr) будет правильно управляться, если вы не измените return_value_policy . Если вы измените политику метода, выставленного на python, чтобы он возвращал ссылку на общий указатель, тогда вы можете создавать проблемы, так же, как передача общих указателей вокруг ссылок c ++ может вызвать проблемы.

(Кроме того, вы должны использовать make_shared<A>(...) в предпочтении shared_ptr<A>(new A(...)) .)

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

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

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

  • Cython и fortran - как скомпилировать без f2py
  • чтение глобальной переменной python в c
  • Символ «Ctypes» не найден »для динамической библиотеки в OSX
  • Приложение Python / Qt / SQLite3 не запускается при установке с помощью Inno Setup
  • Selenium Webdriver + PhantomJS остается примерно: пустым для определенного сайта
  • Узнайте, если / какая библиотека BLAS используется Numpy
  • У меня Python на моей системе Ubuntu, но gcc не может найти Python.h
  • Как реализовать язык сценариев в приложении C?
  •  
    Interesting Posts for Van-Lav

    NameError: глобальное имя «xrange» не определено в Python 3

    Обтекание списком python как операции среза

    преобразовать верхнюю / нижнюю треугольную часть симметричной матрицы (2D-массив) в 1D-массив и вернуть его в 2D-формат

    Как импортировать пакет с помощью __import __ (), когда имя пакета известно только во время выполнения?

    Модуль% в шаблоне Django

    forwardfill в сочетании с вычислением (метод = 'ffill' * xyz) в python pandas

    Как объединить два списка в словарь в Python?

    Есть ли способ скопировать только структуру (а не данные) Pandas DataFrame?

    Почему Python решил отказаться от постоянных ссылок?

    Создание цветного изображения из изображения в оттенках серого

    Python IDE с отладкой и интеграцией iPython?

    Анализ IP-адреса / сети из текстового файла с использованием python

    Как найти максимальный продукт двух элементов в списке?

    Предотвращение сбоя ядра Python при запуске приложения в QT

    Python – абсолютный импорт из подпапки

    Python - лучший язык программирования в мире.