El problema: he envuelto un código de C++ en python usando SWIG. En el lado de Python, quiero tomar un puntero C++ envuelto y convertirlo en un puntero a una subclase. He agregado una nueva función de C++ al archivo SWIG .i que realiza este down-casting, pero cuando lo llamo desde python, obtengo un TypeError.¿Cómo puedo descifrar un objeto de C++ desde un contenedor SWIG de python?
Aquí están los detalles:
Tengo dos clases de C++, la base y derivada. Derived es una subclase de Base. Tengo una tercera clase, Container, que contiene un Derived y proporciona un acceso a ella. El descriptor de acceso devuelve el Derivado como base const &, como se muestra:
class Container {
public:
const Base& GetBase() const {
return derived_;
}
private:
Derived derived_;
};
me he envuelto estas clases en Python usando el TRAGO. En mi código de Python, me gustaría bajar la referencia Base de nuevo a Derived. Para ello, he escrito en el trago .i presentar una función auxiliar en C++, que hace la baja calidad:
%inline %{
Derived* CastToDerived(Base* base) {
return static_cast<Derived*>(base);
}
%}
En mi código Python, llamo a esta función, derribando:
base = container.GetBase()
derived = CastToDerived(base)
Cuando lo hago, me sale el siguiente error:
TypeError: in method 'CastToDerived', argument 1 of type 'Base *'
¿Por qué puede estar pasando esto?
Como referencia, aquí están los bits relevantes del archivo .cxx generado por SWIG; a saber, la función original, y su doppelganger ified-python-interface:
Derived* CastToDerived(Base* base) {
return static_cast<Derived*>(base);
}
// (lots of other generated code omitted)
SWIGINTERN PyObject *_wrap_CastToDerived(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
Base *arg1 = (Base *) 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
PyObject * obj0 = 0 ;
Derived *result = 0 ;
if (!PyArg_ParseTuple(args,(char *)"O:CastToDerived",&obj0)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Base, 0 | 0);
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CastToDerived" "', argument " "1"" of type '" "Base *""'");
}
arg1 = reinterpret_cast< Base * >(argp1);
result = (Derived *)CastToDerived(arg1);
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Derived, 0 | 0);
return resultobj;
fail:
return NULL;
}
Cualquier ayuda sería muy apreciada.
- Matt
lo que hace el código generado para GetBase() parece? El error significa que el objeto que se pasa a CastToDerived no es el tipo correcto, ¿de qué tipo es? –
Por lo que vale, intenté crear un ejemplo basado en lo anterior, usando el truco 1.3.40, y no obtuve este error. –
Tan extraño ... Intenté escribir algo como tu ejemplo, Chris, y de hecho funcionó. Como era de esperar, el código con el que estoy teniendo problemas no es un problema de juguete, simplemente lo modifiqué para hacerlo lo suficientemente corto como para caber en una pregunta. Mi solución actual es definir la función CastToDerived en mi biblioteca C++, en lugar de un bloque% inline% {...%} en el archivo .i. Eso soluciona el problema. ¿Tal vez ese detalle podría ser una pista para la persona correcta? Todavía me gustaría poder hacerlo sin agregar ayudantes de SWIG a mi biblioteca de C++. – SuperElectric