У меня есть библиотека, которая создает объекты (экземпляры класса A) и передает их в программу python, которая должна иметь возможность вызывать их методы.
В основном у меня есть экземпляры класса С++, и я хочу использовать их из python. Иногда этот объект должен быть возвращен на С++ для некоторых манипуляций.
Я создал следующий файл-оболочку (предположим, что функция New
вызывается где-то в коде С++):
#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
. Я не вставлял это, но позвольте сказать, что для этой цели я использую механизм обратного вызова.
Этот код работает, но у меня есть несколько вопросов:
-
В функции Count (и во всех других функциях манипуляции с С++) это нормально передать
a
, как это, или лучше сделать что-то вродеconst shared_ptr<A>&
? В фрагментах кода, которые я нашел в документации по форсированию python, часто используется ссылка, но я не понимаю разницы (кроме, конечно, более высокого ссылочного счетчика). -
Является ли этот код "безопасным"? Когда я передаю существующий_инстамент на python, его счетчик будет увеличиваться (только один раз, даже если в python я делаю больше копий объекта, конечно), поэтому нет никакого способа, чтобы код С++ мог уничтожить объект, поскольку python имеет место по крайней мере, "копией". Я прав? Я пытался играть с указателями, и, похоже, я прав, я просто хочу быть уверен.
-
Я хочу, чтобы python не создавал экземпляры A. Они должны передаваться только из кода С++. Как я мог это достичь? EDIT: найдено, мне просто нужно использовать no_init и noncopyable:
class_<A, boost::noncopyable>("A", no_init)