Il problema: ho avvolto del codice C++ in python usando SWIG. Dal lato python, voglio prendere un puntatore C++ avvolto e farlo ruotare verso il basso per essere un puntatore a una sottoclasse. Ho aggiunto una nuova funzione C++ al file SWI .i che esegue questo down-casting, ma quando lo chiamo da python, ottengo un TypeError.Come si esegue il down-cast di un oggetto C++ da un wrapper SWIG python?
Ecco i dettagli:
Ho due classi C++, di base e derivati. Derivato è una sottoclasse di Base. Ho una terza classe, Container, che contiene un derivato e fornisce un accesso ad esso. La funzione di accesso restituisce il Derivato come base const &, come mostrato:
class Container {
public:
const Base& GetBase() const {
return derived_;
}
private:
Derived derived_;
};
ho avvolto queste classi in Python utilizzando SWIG. Nel mio codice Python, vorrei ridiscendere il riferimento Base su un derivato. Per fare questo, ho scritto nella sorso .i presentare una funzione di supporto in C++ che fa il down-casting:
%inline %{
Derived* CastToDerived(Base* base) {
return static_cast<Derived*>(base);
}
%}
Nel mio codice python, Io chiamo questo down-colata funzione:
base = container.GetBase()
derived = CastToDerived(base)
Quando lo faccio, ottengo il seguente errore:
TypeError: in method 'CastToDerived', argument 1 of type 'Base *'
Perché possa questo accadere?
Per riferimento, ecco i bit rilevanti del file .cxx generato da SWIG; cioè la funzione originale, e la sua doppelganger pitone-interfaccia-ified:
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;
}
Qualsiasi aiuto sarebbe molto apprezzato.
- Matt
ciò che il codice generato per getBase() simile? L'errore indica che l'oggetto passato a CastToDerived non è il tipo giusto, di che tipo è? –
Per quello che vale, ho appena provato a creare un esempio basato su quanto sopra, usando swig 1.3.40, e non ho ricevuto questo errore. –
Così strano ... Ho provato a scrivere qualcosa come il tuo esempio, Chris, e in effetti ha funzionato. Come potreste aspettarvi, il codice con cui ho effettivamente dei problemi non è un problema con i giocattoli, ma ho solo pensato che fosse abbastanza breve da adattarsi a una domanda. La mia soluzione attuale consiste nel definire la funzione CastToDerived nella mia libreria C++, invece che in un blocco% inline% {...%} nel file .i. Questo risolve il problema. Forse quel dettaglio potrebbe essere un suggerimento per la persona giusta? Vorrei ancora poter fare a meno di aggiungere gli helper SWIG alla mia libreria C++. – SuperElectric