Pregunta

Me he dado cuenta de que trago ofrece toda una serie de funciones para permitir typecasting objetos a sus clases padre. Sin embargo, en C ++ se puede producir una función como la siguiente:

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

donde "a" es el padre de clases "B" y "C". Entonces se puede encasillarse el puntero devuelto a ser un tipo "B" o de tipo "C" en la conveniencia de uno como:

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

¿Hay alguna manera de que pueda encasillarse un objeto que he recibido de un genérico triple productor de la función en tiempo de ejecución en el lenguaje de programación utilizando los envoltorios? (En mi caso, Lua?) Tengo una función que podría producir una de cerca de un centenar clases posibles, y me gustaría evitar escribir una estructura de conmutación enormes que tendría que mantener en C ++. En el punto donde recibo el puntero genérico, también tengo una cadena que representa el tipo de datos que me gustaría echarlo a.

¿Alguna idea? Gracias!

- Editar -

Me he dado cuenta de que el TRAGO ofrece para generar constructores de copia para todas mis clases. Si tuviera que generar ellos, podría hacer algo como lo siguiente ?:

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

var y tienen entonces una instancia de la clase que hereda de que sabe es una instancia de la clase que hereda?

¿Fue útil?

Solución

he desarrollado una solución a mi problema. Soy nuevo en la recolección de basura de lua, así que no estoy seguro si es la memoria a prueba de fugas, pero hace lo que necesito que haga. (Tampoco es infalible -. Si se pasa un tipo de datos válido y un objeto que no se debe interpretar a ese tipo de datos, mala materia resultará)

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

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

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

Espero que ayude a alguien!

Otros consejos

He resuelto esto usando un typemap y un campo de clase que tiene la estructura TRAGO swig_type_info del tipo de clase.

Por ejemplo. Suponga que tiene un BaseClass que contiene la funcionalidad de lista enlazada básica, sin embargo, los nodos reales pueden ser de cualquier clase derivada de BaseClass. Por lo tanto usted tiene una lista enlazada polimórfica. En la clase base defino un valor "stored_swig_info" que mantiene el resultado de la llamada a SWIG_TypeQuery (..). Me puse este valor durante la inicialización. A continuación, en tiempo de ejecución se puede utilizar lo siguiente:

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

Y en la clase real Módulos del constructor hace lo siguiente:

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

...

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

Una nota sobre la aplicación. Asegúrese de que esta inicialización se llama después de que el módulo de lua se ha inicializado o bien el typetabel TRAGO aún no está vacío.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top