Das ist eine knifflige Frage.
In C # 4 können Sie dynamic verwenden, um anzugeben, dass der Typ zur Laufzeit bekannt ist.
Nach meinem persönlichen Verständnis benötigt c ++ jedoch den zum Zeitpunkt der Kompilierung bekannten Typ. Daher könnten Sie in Erwägung ziehen, object
zu verwenden, aber object
in C # ist ein vorhandener Typ.
Für das Konzept von Multi-Typ, Einzelwert (AKA-Polymorphismus) von VARIANT müssen Sie in C # keinen entsprechenden Typ finden, sondern nur Ihre Klassen und Schnittstellen definieren. Sie können immer auf ein Objekt als seine Schnittstelle verweisen, die die Klasse implementiert.
Wenn Sie den Code portieren und eine Syntax ermitteln, die Sie einfach in LHS verwenden können und die Berücksichtigung des Typs zur Kompilierungszeit bekannt ist, verwenden Sie var .
Nun, es gibt tatsächlich zwei Varianten in C ++: boost :: variant und COM-Variante. Die Lösung folgt mehr oder weniger der gleichen Idee, aber ersteres ist komplexer. Ich nehme an, dass du meinst, das letztere zu benutzen.
Lassen Sie mich zuallererst sagen, dass dies etwas ist, das Sie, wenn möglich, nicht verwenden sollten. Das heißt, so machen Sie es: -)
Varianten und Interop
Manchmal werden Varianten im Interop von verwendet, wenn die Byte-Darstellung die gleiche sein soll.
Wenn Sie mit Interop arbeiten, stellen Sie sicher, dass Sie die VariantWrapper
-Klasse in MSDN auschecken, damit es so funktioniert.
Varianten und Überlegungen zur Portierung
Varianten werden meistens in APIs verwendet und normalerweise wie folgt:
%Vor% Der Grund, warum es in C ++ so gemacht wird, ist, dass es keine Base object
-Klasse gibt und Sie daher etwas ähnliches brauchen. Der einfachste Weg dies zu portieren, ist die Signatur in:
Wenn Sie jedoch trotzdem portieren, sollten Sie auch diese beiden Aspekte berücksichtigen, da sie zur Kompilierungszeit aufgelöst werden und Ihnen den großen "Schalter" ersparen können, der normalerweise in der Methode Foo
folgt:
Varianten und Byte-Konsistenz
In seltenen Fällen müssen Sie die Bytes selbst manipulieren.
Im Wesentlichen ist die Variante nur eine große Union von Werttypen, die in einen einzigen Werttyp (struct) eingeschlossen sind. In C ++ können Sie dem Heap einen Werttyp zuordnen, da eine Struktur die gleiche ist wie eine Klasse (gut sortiert). Wie der Werttyp verwendet wird, ist nur ein bisschen wichtig, aber dazu später mehr.
Union bedeutet einfach, dass Sie alle Daten im Speicher überlappen werden. Beachten Sie, wie ich den Werttyp oben explizit notiert habe. Für Varianten ist das im Grunde genommen das, worum es geht. Dies gibt uns auch eine Möglichkeit, es zu testen - nämlich einen anderen Wert in der Struktur zu überprüfen.
Die Art und Weise, dies in C # zu tun, besteht darin, das Attribut StructLayout
in einem Werttyp zu verwenden, der im Prinzip wie folgt funktioniert:
C ++ - Varianten können auch auf dem Heap gespeichert werden, wie ich bereits erwähnt habe. Wenn Sie dies tun, möchten Sie wahrscheinlich immer noch, dass die Speichersignatur identisch ist. Der Weg, dies zu tun, besteht darin, die Variant-Struktur, die wir früher gebaut haben, zu boxen, indem wir sie einfach in object
einschließen.
Wenn .NET eine COM-Schnittstelle implementiert , verwenden Sie stattdessen VARIANT * .
Dann umgehen Sie das Marshalling auf der .NET-Empfangsseite, indem Sie den IntPtr -Typ verwenden, um den Zeiger zu empfangen.
%Vor%Wenn Sie auf ein VT_UNKNOWN zugreifen, das auf eine COM-Schnittstellenobjektinstanz verweist,
%Vor%wird den Trick machen, aber achten Sie darauf, dass Sie eine neu zugewiesene VARIANT nicht verwenden und der .NET-Implementierung ihren Besitz zuweisen, ohne sie irgendwo zu entfernen ...
Für komplexeren Code könnten Sie lesen dieser Artikel , der auch über Speicherverwaltung spricht.
Machen wir einen Schritt zurück. Früher oder später wollen wir die tatsächlichen Daten im VARIANT. Ein VARIANT ist nur ein Halter für aussagekräftige Daten. Angenommen, wir haben die VARIANT in eine Art Objekt in C # konvertiert, das den Variant-Typ und einen rohen Puffer unter der .NET-Haube hatte (z. B. können .NET-Strings den Raw-Puffer freilegen). An diesem Punkt müsste der VARIANT-Typ aus dem Objekt und den Rohdaten bestimmt werden, die in den durch die Variante spezifizierten Datentyp umgewandelt oder umgewandelt werden, und dann ein neues Objekt, z. string / int / etc. aus den Rohdaten.
Anstatt sich darum zu sorgen, dass die VARIANT an C # übergeben wird, sollten Sie sich den Variant-Datentyp ansehen und ihn in C ++ in den tatsächlichen Datentyp konvertieren und an C # übergeben.
Wenn zum Beispiel der Typ VARIANT VT_INT ist, dann holen Sie sich den int von der Variante und können etwas wie:
verwenden %Vor%returnInt kann als Out-Parameter von einer C ++ - Funktion in einer C ++ - DLL zurückgegeben werden, die von C # aufgerufen werden kann. Die C ++ DLL benötigt die Option / clr.
Funktion würde wie aussehen: -
%Vor%Kann einen ähnlichen Ansatz für andere Datentypen verwenden. Es ist nur natürlich, eine VARIANT von VT_INT ist wirklich genau wie ein int, es ist nicht so, als ob es eine große Umwandlung gibt, du nimmst nur den tatsächlichen Wert aus der VARIANT zu der Zeit, wenn du daran interessiert bist wie du würde, wenn Sie einen geraden Ganzzahlwert von C ++ nach C # übergeben würden. Sie müssten das gcnew trotzdem tun.
Tags und Links c# c++ type-conversion variant