Wie kann man in C # mit einer von SWIG generierten Schnittstelle richtig downcasten?

Ich habe eine sehr große und ausgereifte C ++ - Codebasis, auf der ich SWIG verwenden möchte, um eine C # -Schnittstelle für zu generieren. Ich kann den eigentlichen C ++ - Code nicht ändern, aber wir können alles, was SWIG anbietet, zur Erweiterung / Aktualisierung verwenden. Ich stehe vor einem Problem, bei dem eine C ++ - Funktion, die wie folgt geschrieben ist, Probleme in C # verursacht.

A* SomeClass::next(A*)

Der Anrufer könnte Folgendes tun:

A* acurr = 0;
while( (acurr = sc->next(acurr)) != 0 ){
    if( acurr isoftype B ){
        B* b = (B*)a;
        ...do some stuff with b..
    }
    elseif( acurr isoftype C )
    ...
}

Im Wesentlichen durchlaufen Sie einen Container mit Elementen, die je nach ihrem tatsächlichen Typ etwas anderes bewirken. Die von SWIG generierte C # -Schicht für die Funktion "next" führt leider Folgendes aus:

return new A();

Der aufrufende Code in C # kann also nicht feststellen, ob das zurückgegebene Objekt tatsächlich eine abgeleitete Klasse ist oder nicht. Es scheint also immer die Basisklasse zu sein (was Sinn macht). Ich bin auf verschiedene Lösungen gestoßen:

Verwenden Sie das Schlüsselwort% extend SWIG, um eine Methode für ein Objekt hinzuzufügen und schließlich dynamic_cast aufzurufen. Der Nachteil dieses Ansatzes besteht meines Erachtens darin, dass Sie die Vererbungshierarchie kennen müssen. In meinem Fall ist es ziemlich groß und ich sehe dies als Wartungsproblem.Verwenden Sie das Schlüsselwort% factory, um die Methode und die abgeleiteten Typen anzugeben, und lassen Sie SWIG den dynamic_cast-Code automatisch generieren. Dies scheint eine bessere Lösung zu sein, als die erste, aber bei genauerer Betrachtung müssen Sie immer noch alle Methoden und alle möglichen abgeleiteten Typen suchen, die zurückgegeben werden könnten. Wieder ein riesiges Wartungsproblem. Ich wünschte, ich hätte einen Doku-Link dafür, aber ich kann keinen finden. Ich habe mich anhand des Beispielcodes, der mit SWIG geliefert wird, über diese Funktionalität informiert.Erstellen Sie eine C # -Methode, um eine Instanz des abgeleiteten Objekts zu erstellen und den cPtr auf die neue Instanz zu übertragen. Ich halte das zwar für ungeschickt, aber es funktioniert. Unten sehen Sie ein Beispiel.
    public static object castTo(object fromObj, Type toType)
    {
        object retval = null;

        BaseClass fromObj2 = fromObj as BaseClass;
        HandleRef hr = BaseClass.getCPtr(fromObj2);
        IntPtr cPtr = hr.Handle;
        object toObj = Activator.CreateInstance(toType, cPtr, false);

        // make sure it actually is what we think it is
        if (fromObj.GetType().IsInstanceOfType(toObj))
        {
            return toObj;
        }

        return retval;
    }

Sind das wirklich die Optionen? Und wenn ich nicht bereit bin, alle existierenden Funktionen und Klassenableitungen zu durchforsten, habe ich dann noch Platz 3? Jede Hilfe wäre dankbar.

Antworten auf die Frage(3)

Ihre Antwort auf die Frage