Question

Je remarque que Swig fournit toute une série de fonctions pour permettre des objets typecasting à leurs classes parentes. Cependant, en C ++ on peut produire une fonction comme suit:

A * getAnObject()
{
  if(someBoolean)
    return (A *) new B;
  else
    return (A *) new C;
}

Où "A" est le parent des classes "B" et "C". On peut alors cataloguée le pointeur retourné en étant un type « B » ou de type « C » à l'une de convenance comme:

B * some_var = (B *) getAnObject();

Est-il possible que je peux typecast un objet que je l'ai reçu d'une fonction pointeur de production générique lors de l'exécution dans le langage de script en utilisant les emballages? (Dans mon cas, Lua?) J'ai une fonction qui pourrait produire une d'une centaine de classes possibles, et je voudrais éviter d'écrire une énorme structure de commutateur que je dois maintenir en C ++. Au point où je reçois le pointeur générique, j'ai aussi une représentation de chaîne du type de données que je voudrais jeter à.

Toutes les pensées? Merci!

- EDIT -

Je remarque que SWIG propose de générer des constructeurs de copie pour toutes mes classes. Si je l'avais générer ceux-ci, que je pouvais faire quelque chose comme ce qui suit ?:

var = myModule.getAnObject(); -- Function that returns an object type-cast down to a pointer of the parent class, as in the function getAnObject() above.
var = myModule.ClassThatExtendsBaseClass(var); -- A copy constructor that SWIG theoretically creates for me

et ont var alors une instance de la classe héritant que sait c'est une instance de la classe héritant?

Était-ce utile?

La solution

J'ai développé une solution à mon problème. Je suis nouveau à la collecte des ordures de lua, donc je ne suis pas sûr que ce soit mémoire étanche, mais il fait ce que je besoin de le faire. (Il est pas non plus infaillible -. Si vous passez un type de données valide et un objet qui ne doit pas être jeté comme ce type de données, mauvaises choses entraînera)

=============================================== ==================================

static int lua_typecast_Object_I(lua_State *L)
{
        void * myDataPtr;
        void ** ptrToPtr = &myDataPtr;

        // Attempt to convert the first parameter to a pointer of
        // the lowest parent type from which all other data types 
        // inherit. e.g. "Object_I"

        if (!SWIG_IsOK(SWIG_ConvertPtr(L, 1, ptrToPtr, SWIGTYPE_p_Namespace1__Object_I, 0)))
        {
                lua_pushnumber(L, -1);
                lua_pushstring(L,"Pointer conversion in typecast function failed.");
                return 2;
        }

        const char * type_name = luaL_checkstring(L, 2);

        // Search the SWIG module for a swig_type_info that contains the data
        // type string that was passed as the second parameter

        swig_module_info* module=SWIG_GetModule(L);
        swig_type_info *type = SWIG_TypeQueryModule(module,module,type_name);
        if(type == NULL)
        {
                lua_pushnumber(L, -2);
                lua_pushstring(L,"Failed to find swig_type_info for specified type.");
                return 2;
        }

        // Using the swig_type_info that we found, create a new object on 
        // the stack of the desired data type and return.

        SWIG_Lua_NewPointerObj(L, myDataPtr, type, 0);
        return 1;
}

=============================================== ==================================

L'espoir qui aide quelqu'un!

Autres conseils

I résolu ce en utilisant un typemap et un champ de classe qui contient la structure de SWIG swig_type_info du type de classe.

Par exemple. Supposons que vous ayez un BaseClass qui contient la fonctionnalité de liste chaînée de base, mais les nœuds réels peuvent être une classe dérivée de BaseClass. Ainsi, vous avez une liste liée polymorphes. Dans la classe de base I définir une valeur « stored_swig_info » qui détient le résultat de l'appel à SWIG_TypeQuery (..). Je mis cette valeur lors de l'initialisation. Ensuite, lors de l'exécution vous pouvez utiliser ce qui suit:

// The typemap converts a function result from C->Lua. 
%typemap(out) BaseClass* {
   // stored_swig_info is set by calling SWIG_TypeQuery("DerivedClass *"), done at
   // initialization, so it can be used here to read the actual type
   swig_type_info* info = $1->stored_swig_info;
   SWIG_NewPointerObj(L, $1, info, 0); SWIG_arg++;
};

// base class
class BaseClass {
private:
  swig_type_info *stored_swig_info;
public:
  BaseClass* next () { ... };
  BaseClass* prev () { ... };
};

// derived class
class DerivedClass: public BaseClass {
};

Et dans la classe réelle modules constructeur effectue les opérations suivantes:

BaseClass::BaseClass () {
  ...
  stored_swig_info = SWIG_TypeQuery("BaseClass *");
  ...
}

...

DerivedClass::DerivedClass () {
  ...
  stored_swig_info = SWIG_TypeQuery("DerivedClass *");
  ...
}

Une note sur la mise en œuvre. Assurez-vous que cette initialisation est appelée après le module lua est initialisé ou bien le typetabel SWIG est pas encore rempli.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top