2012-08-31 14 views
9

Tengo un objeto que se mantiene en un shared_ptr en C++. El objeto se accede a través de los enlaces de python desde dentro de python y se pasa a otra función de C++ vinculada que intenta mantenerla. Parece que cuando el objeto va de C++ a Python se convierte de un shared_ptr a un objeto python. Luego, cuando vuelve a C++, se convierte del objeto python en un nuevo shared_ptr; sin embargo, este shared_ptr no está relacionado con el holding compartido shared_ptr.¿Es posible pasar un impulso shared_ptr de C++ a Python y volver a C++

¿Es posible configurar los enlaces boost-python para que la conversión del objeto python a shared_ptr haga referencia a los elementos internos shared_ptr originales?

A continuación se muestra el código abreviado que he utilizado para mostrar el problema.

En este ejemplo, un objeto se mantiene inicialmente en un shared_ptr llamado s_inital. Se capta desde dentro de python a través de la función getSharedPtr, luego se vuelve a presionar en C++ a través de la función putSharedPtr. Dentro de putSharedPtr, se copia en el archivo weak_ptr s_copied. La inspección de los punteros en el depurador muestra que shared_ptr utilizado en putSharedPtr no tiene los mismos elementos internos de recuento de referencias que s_initial. La afirmación final se activará porque el puntero débil s_copied solo se relacionó con un solo puntero fuerte (el puntero utilizado en putSharedPtr) y ese puntero se destruyó una vez que putSharedPtr finalizó.

static shared_ptr<Captured> s_initial; 
static weak_ptr<Captured> s_copied; 

class UseSharedPtr 
{ 
public: 
    shared_ptr<Captured> getSharedPtr() 
    { 
     return s_initial; 
    } 

    void putSharedPtr(shared_ptr<Captured> ptr) 
    { 
     s_copied = ptr; 
    } 
}; 


BOOST_PYTHON_MODULE(test) 
{ 
    class_<Captured, shared_ptr<Captured>, boost::noncopyable>("Captured", no_init); 
    class_<UseSharedPtr, boost::noncopyable>("UseSharedPtr", init<>()) 
     .def("getSharedPtr", &UseSharedPtr::getSharedPtr) 
     .def("putSharedPtr", &UseSharedPtr::putSharedPtr) 
    ; 
} 



    s_initial = make_shared<Captured>(); 

    const char* chunk = "\ 
from test import UseSharedPtr \n\ 
x = UseSharedPtr() \n\ 
ptr = x.getSharedPtr() \n\ 
x.putSharedPtr(ptr)\n\ 
del x \n\ 
del ptr \n\ 
"; 
    object result = exec(chunk, mainNamespace, mainNamespace); 

    assert(s_copied.lock()); 
+0

¿Cuál es el propósito de toda la clase 'UseSharedPtr'? Así como 'Captured' está expuesto ahora, boost :: python lo manejará correctamente. – eudoxos

+0

Creo que esto solo fue un ejemplo. Mientras boost.python llamará correctamente a los métodos de la clase compartida, tiene problemas para pasar el parámetro 'shared_ptr' a otras clases. – Tali

Respuesta

0

Es necesario class_<UseSharedPtr, shared_ptr<UseSharedPtr>, boost::noncopyable> modo que impulso :: pitón sabe que debe gestionar el objeto utilizando shared_ptr. Haga que su ejemplo sea compilable si quiere que lo verifique.

+0

El indicador 'shared_ptr' y' noncopyable' ya están presentes en el ejemplo publicado. – Tali

0

Una solución fácil, pero fea sería utilizar enable_shared_from_this() para la clase Captured y obtener un nuevo shared_ptr para cada parámetro utilizando shared_from_this().

void putSharedPtr(shared_ptr<Captured> ptr) 
{ 
    s_copied = ptr->shared_from_this(); 
} 
Cuestiones relacionadas