Я заворачиваю функцию, которая всегда возвращает указатель на уже удерживаемый объект C++.
Один из способов сделать это — захватить механизмы, используемые для обертывания класса виртуальными функциями. Если вы сделаете класс обертки с первоначальным аргументом конструктора PyObject* и сохраните этот PyObject* как «я», вы можете вернуться к нему, отбрасывая до этого типа обертки тонкую функцию обертки. Например:
class X { X(int); virtual ~X(); ... };
X* f();
struct X_wrap : X
{
X_wrap(PyObject* self, int v) : self(self), X(v) {}
PyObject* self;
};
handle<> f_wrap()
{
X_wrap* xw = dynamic_cast<X_wrap*>(f());
assert(xw != 0);
return handle<>(borrowed(xw->self));
}
...
def("f", f_wrap());
class_<X,X_wrap,boost::noncopyable>("X", init<int>())
...
;
Конечно, если у X нет виртуальных функций, вам придется использовать<static_cast
>вместо<dynamic_cast
>без проверки времени выполнения. Этот подход также работает только в том случае, если объект<X
>был построен на Python, потому что<X
>, построенные на C++, конечно, никогда не являются объектами<X_wrap
>.
Другой подход к этому требует, чтобы вы немного изменили свой код C++; если это вариант для вас, это может быть лучшим способом. Работа, к которой мы все равно стремились. Когда<shared_ptr<X>
>преобразуется из Python, shared_ptr фактически управляет ссылкой на содержащий объект Python. Когда файл share_ptrпреобразуется обратно в Python, библиотека проверяет, является ли он одним из тех «управляющих объектами Python», и если да, то просто возвращает исходный объект Python. Так что вы можете просто написать<object(p)
>, чтобы получить объект Python обратно. Чтобы использовать это, вы должны быть в состоянии изменить код C++, который вы заворачиваете, чтобы он имел дело с shared_ptr вместо исходных указателей.
Есть и другие подходы. Функции, которые получают объект Python, который вы в конечном итоге хотите вернуть, могут быть обернуты тонкой оберткой, которая записывает соответствие между адресом объекта и его содержащим объектом Python, и вы можете увидеть функцию f_wrap в этом отображении, чтобы получить объект Python.