Domanda

Ho notato che Swig fornisce tutta una serie di funzioni per consentire il typecasting di oggetti nelle loro classi madri.Tuttavia, in C++ è possibile produrre una funzione come la seguente:

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

Dove "A" è il genitore delle classi "B" e "C".È quindi possibile digitare il puntatore restituito in un tipo "B" o "C" a proprio piacimento come:

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

Esiste un modo per digitare un oggetto che ho ricevuto da una funzione di produzione di puntatori generici in fase di esecuzione nel linguaggio di scripting utilizzando i wrapper?(Nel mio caso, Lua?) Ho una funzione che potrebbe produrre una tra un centinaio di classi possibili e vorrei evitare di scrivere un'enorme struttura di switch che dovrei mantenere in C++.Nel punto in cui ricevo il puntatore generico, ho anche una rappresentazione di stringa del tipo di dati a cui vorrei trasmetterlo.

qualche idea?Grazie!

-- MODIFICARE --

Ho notato che SWIG si offre di generare costruttori di copie per tutte le mie classi.Se li avessi generati, potrei fare qualcosa di simile a quanto segue?:

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

e fare in modo che var sia un'istanza della classe ereditaria that conosce è un'istanza della classe che eredita?

È stato utile?

Soluzione

Ho sviluppato una soluzione al mio problema. Sono nuovo di garbage collection di lua, quindi non sono sicuro se è-a prova di perdite di memoria, ma fa quello che ho bisogno di fare. (E 'anche non infallibile -. Se si passa un tipo di dati valido e un oggetto che non dovrebbe essere scelto per il ruolo che tipo di dati, cose cattive si tradurrà)

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

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;
}

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

La speranza che aiuta qualcuno!

Altri suggerimenti

Ho risolto questo problema utilizzando una typemap e un campo di classe che contiene la struttura SWIG swig_type_info del tipo di classe.

Per esempio.Supponiamo di avere una BaseClass che contiene funzionalità di base dell'elenco collegato, ma i nodi effettivi possono essere qualsiasi classe derivata da BaseClass.Quindi hai un elenco collegato polimorfico.Nella classe base definisco un valore "stored_swig_info" che contiene il risultato della chiamata a SWIG_TypeQuery(..).Ho impostato questo valore durante l'inizializzazione.Quindi in fase di esecuzione puoi usare quanto segue:

// 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 {
};

E nei moduli di classe effettivi il costruttore fa quanto segue:

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

...

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

Una nota sull'implementazione.Assicurati che questa inizializzazione venga chiamata dopo che il modulo lua è stato inizializzato, altrimenti la tabella dei caratteri SWIG non è ancora riempita.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top