Le problème: J'ai enveloppé du code C++ en python en utilisant SWIG. Du côté de python, je veux prendre un pointeur c + + enveloppé et le transformer en un pointeur vers une sous-classe. J'ai ajouté une nouvelle fonction C++ au fichier SWIG .i qui fait ce down-casting, mais quand je l'appelle depuis python, j'obtiens un TypeError.Comment est-ce que je descends un objet C++ à partir d'un wrapper SWX python?
Voici les détails:
J'ai deux classes C++, de base et dérivés. Derived est une sous-classe de Base. J'ai une troisième classe, Container, qui contient un dérivé, et lui fournit un accesseur. L'accesseur retourne la base Derived comme const &, comme le montre:
class Container {
public:
const Base& GetBase() const {
return derived_;
}
private:
Derived derived_;
};
J'ai enveloppé ces classes en python utilisant SWIG. Dans mon code python, je souhaite redescendre la référence de base vers un dérivé. Pour ce faire, je l'ai écrit dans le rasade .i fichier une fonction d'assistance en C++ qui fait le bas-casting:
%inline %{
Derived* CastToDerived(Base* base) {
return static_cast<Derived*>(base);
}
%}
Dans mon code python, j'appelle cette fonction vers le bas-casting:
base = container.GetBase()
derived = CastToDerived(base)
Quand je le fais, je reçois l'erreur suivante:
TypeError: in method 'CastToDerived', argument 1 of type 'Base *'
Pourquoi pourrait-il se passer?
Pour référence, voici les bits pertinents du fichier .cxx généré par SWIG; à savoir la fonction d'origine, et son interface ified-python Doppelganger:
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;
}
Toute aide serait grandement appréciée.
- Matt
ce que fait le code généré pour getBase() ressembler? L'erreur signifie que l'objet transmis à CastToDerived n'est pas le bon type - de quel type s'agit-il? –
Pour ce que ça vaut, j'ai juste essayé de créer un exemple basé sur ce qui précède, en utilisant swig 1.3.40, et je n'ai pas eu cette erreur. –
Si étrange ... J'ai essayé d'écrire quelque chose comme votre exemple, Chris, et en effet cela a fonctionné. Comme vous pouvez vous y attendre, le code avec lequel j'ai des problèmes n'est pas un problème de jouet, je l'ai juste fait pour le rendre assez court pour répondre à une question. Ma solution de contournement actuelle consiste à définir la fonction CastToDerived dans ma bibliothèque C++, au lieu d'un bloc% inline% {...%} dans le fichier .i. Cela résout le problème. Peut-être que ce détail pourrait être un indice à la bonne personne? Je souhaite toujours que je pourrais faire sans ajouter des aides de SWIG à ma bibliothèque de C++. – SuperElectric