2009-06-08 6 views
2

Ich stelle fest, dass Swig eine ganze Reihe von Funktionen bietet, um Objekte in ihre übergeordneten Klassen typisieren zu können. Jedoch ist in C++ eine Funktion wie folgt herstellen kann:Swig Typumwandlung in abgeleitete Klasse?

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

wobei „A“ der Haupt der Klassen „B“ und „C“. Man kann dann typisierte die Zeiger wieder in seine ein Typ „B“ oder „C“ an einem der Bequemlichkeit wie:

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

Gibt es irgendeine Weise, die ich ein Objekt typisieren kann ich von einem generic-Zeiger- erhalten Funktion zur Laufzeit in der Skriptsprache unter Verwendung der Wrapper erzeugen? (In meinem Fall, Lua?) Ich habe eine Funktion, die eine von etwa hundert möglichen Klassen erzeugen könnte, und ich möchte vermeiden, eine enorme Switch-Struktur zu schreiben, die ich in C++ führen müsste. An dem Punkt, an dem ich den generischen Zeiger erhalte, habe ich auch eine String-Darstellung des Datentyps, in den ich ihn umwandeln möchte.

Irgendwelche Gedanken? Vielen Dank!

- EDIT -

Ich bemerke, dass SWIG Kopierkonstruktoren für alle meine Klassen generieren bietet. Hätte ich es diejenigen erzeugen, konnte ich etwas tun, wie folgt aus ?:

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 

und haben var dann eine Instanz der Klasse inheriting sein, dass weiß, dass es eine Instanz der Klasse ist inheriting?

Antwort

2

Ich entwickelte eine Lösung für mein Problem. Ich bin neu in Lua's Garbage Collection, also bin ich mir nicht sicher, ob es Speicherlecksicher ist, aber es tut, was ich tun muss. (Es ist auch nicht narrensicher - wenn Sie einen gültigen Datentyp und ein Objekt übergeben, das nicht als dieser Datentyp umgewandelt werden soll, wird schlechtes Material zur Folge hat.)

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

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

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

Hoffe, dass jemand hilft!

+1

Die übliche Lua-Konvention für Fehlerrückgaben ist die Rückgabe von nil, "message", wo Sie einen numerischen Code und eine Nachricht zurückgeben.Die Rückgabe von nil erweist sich als sehr einfach, um von jedem anderen "gültigen" Rückgabewert auf der Lua-Seite zu unterscheiden, daher das Idiom. Es ist auch das Muster, das von vielen der Kernmodule gefolgt wird. Alternativ können Sie stattdessen luaL_error() verwenden, da ein Fehler bei der Typbenennung wahrscheinlich ein schwerwiegendes Problem ist. Einzelheiten finden Sie unter http://www.lua.org/manual/5.1/manual.html#luaL_error. – RBerteig

+0

Ich erkenne keine Lecks, aber fühle mich in den SWIG-Interna nicht genug um das zu bestätigen ;-) – RBerteig

1

Ich löste dies mit einem typemap und einem Klassenfeld, das die SWIG-Struktur swig_type_info des Klassentyps enthält.

Zum Beispiel. Angenommen, Sie verfügen über eine BaseClass, die grundlegende Funktionen für verknüpfte Listen enthält. Die tatsächlichen Knoten können jedoch jede von BaseClass abgeleitete Klasse sein. Somit haben Sie eine polymorphe verkettete Liste. In der Basisklasse definiere ich einen Wert "stored_swig_info", der das Ergebnis des Aufrufs an SWIG_TypeQuery (..) enthält. Ich setze diesen Wert während der Initialisierung. Dann zur Laufzeit können Sie die folgende verwenden:

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

Und in der aktuellen Klasse-Module den Konstruktor ist der folgende:

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

... 

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

Ein Hinweis auf die Umsetzung. Stellen Sie sicher, dass diese Initialisierung aufgerufen wird, nachdem das Lua-Modul initialisiert wurde oder das SWIG-Typestabel noch nicht gefüllt ist.