Tengo una biblioteca que crea objetos (instancias de clase A) y los pasa a un programa python que debería poder llamar a sus métodos.pasar instancias de clases C++ a python con boost :: python
Básicamente tengo instancias de clase C++ y quiero usarlas de python. Ocasionalmente, ese objeto debería pasarse a C++ para algunas manipulaciones.
creé el siguiente archivo de envoltura (vamos a suponer que la función New
se llama en alguna parte del código en 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> >();
}
El código carece de la parte en la que la pitón obtiene el existing_instance
. No pegué eso, pero digamos que uso un mecanismo de devolución de llamada para ese propósito.
Este código funciona, pero tengo algunas preguntas:
En la función Count (y en todas las demás funciones de manipulación de C++) es que estaba bien para pasar
a
así o es mejor hacer algo comoconst shared_ptr<A>&
? En los fragmentos de código que encontré en la documentación de boost de python, la referencia se usa a menudo, pero no entiendo la diferencia (aparte de tener un contador de referencia más alto, por supuesto).¿Este código es "seguro"? Cuando paso la instancia_existente a python, su contador se incrementará (solo una vez, incluso si en python hago más copias del objeto, por supuesto), así que no hay forma de que el código C++ pueda destruir el objeto en la medida en que python al menos una "copia". ¿Estoy en lo correcto? Traté de jugar con los punteros y parece que estoy en lo correcto, solo estoy preguntando para estar seguro.
Me gustaría evitar que python cree instancias de A. Solo deberían pasarse desde código C++. ¿Cómo podría lograr eso? EDITAR: encontrado, sólo tiene que utilizar NO_INIT y noncopyable:
class_<A, boost::noncopyable>("A", no_init)
cuál es la diferencia (en la práctica) entre "class_ (" A "NO_INIT)" y "impulso: : python :: class_ > ("A", boost :: python :: no_init) "? El código que publiqué funciona perfectamente incluso sin especificar "boost :: shared_ptr " después de "class_". Entonces, ¿por qué iba a necesitar eso? – Emiliano
Especifica el tipo predeterminado que será empaquetado por una python 'A' - así que si tiene una función C++ que devuelve una 'A', 'A *' shared_ptr o algo similar, y lo expone en python, entonces la el valor de retorno se mantendrá como shared_ptr , que es lo que desea si con frecuencia está pasando estos objetos dentro y fuera de python, ya que toda la propiedad se manejará correctamente. Consulte http://www.boost.org/doc/libs/1_43_0/libs/python/doc/v2/class.html#HeldType (especialmente el punto 2) para obtener más información. –
James