Hier ist, was ich versuche zu tun:
Ich entwickle eine plattformübergreifende IDE (Linux und Windows), die Plugins unterstützt. Ich muss die Erweiterbarkeit mithilfe eines Adapterframeworks unterstützen, das dem von Eclipse ähnelt. Siehe hier für weitere Details, aber im Grunde brauche ich Folgendes:
Lassen Sie Adaptee
und Adapted
völlig unabhängige Klassen sein, die bereits existieren und die wir in keiner Weise ändern dürfen. Ich möchte eine AdapterManager
-Klasse erstellen, die eine Methode
erstellt eine Instanz von Adapted
mit einer Instanz von Adaptee
. Wie genau die Instanz erstellt wird, hängt von einer Adapterfunktion ab, die mit AdapterManager
registriert werden muss. Jedes neue Plug-in sollte in der Lage sein, Adapterfunktionen für beliebige Typen bereitzustellen.
Hier sind meine Gedanken über eine mögliche Lösung und warum es nicht funktioniert:
Die RTTI-Funktionen von C ++ 11 und die Klasse type_info
stellen eine Methode hash_code()
bereit, die für jeden Typ im Programm eine eindeutige Ganzzahl zurückgibt. Siehe hier . Daher könnte AdapterManager
einfach eine Map enthalten, die bei gegebenen Hash-Codes für die Adaptee und Adapter-Klassen einen Funktionszeiger auf die Adapterfunktion zurückgibt. Dies macht die Implementierung der Funktion adapt()
über trivial:
Jedes Plug-in kann das Framework einfach erweitern, indem es einfach eine zusätzliche Funktion in die Map einfügt. Beachten Sie auch, dass jedes Plug-in versuchen kann, eine beliebige Klasse an eine andere Klasse anzupassen und erfolgreich zu sein, wenn eine entsprechende Adapterfunktion mit AdapterManager
registriert ist, unabhängig davon, wer sie registriert hat.
type_info
-Strukturen und möglicherweise anderen hash_code()
-Ergebnissen führen, wodurch der obige Mechanismus durchbrochen wird. Adapterfunktionen, die von einem Plug-In registriert werden, funktionieren möglicherweise nicht immer in einem anderen Plug-In. Fragen:
Update 1:
Dieses Projekt verwendet das Qt-Framework für viele Dinge einschließlich der Plug-in-Infrastruktur. Qt hilft wirklich bei der plattformübergreifenden Entwicklung. Wenn Sie eine Qt-spezifische Lösung für das Problem kennen, ist das auch willkommen.
Update 2:
Der Kommentar von n.m. hat mir gezeigt, dass ich das Problem nur theoretisch kenne und nicht wirklich getestet habe. Also habe ich einige Tests in Windows und Linux mit der folgenden Definition durchgeführt:
Diese Klasse wird in zwei verschiedenen gemeinsam genutzten Bibliotheken / DLLs mit T = int instanziiert. Beide Bibliotheken werden zur Laufzeit explizit geladen. Hier ist, was ich gefunden habe:
In Linux funktioniert alles:
typeid
zurückgegebene Objekt befand sich an der gleichen Adresse. In Windows sind die beiden Instanzen 'etwas' verschieden:
typeid
für die verschiedenen Instanzen gibt type_info
Objekte an verschiedenen Adressen zurück. Diese Objekte sind jedoch gleich, wenn sie mit ==
getestet werden. Die entsprechenden Hash-Codes sind ebenfalls gleich. Es scheint, als ob unter Windows die Gleichheit zwischen den Typen unter Verwendung des Namens des Typs hergestellt wird - was sinnvoll ist. So weit, so gut. dynamic_cast
verwenden, um eine Instanz von TypeIdTest
auf einen abgeleiteten Typ über die Grenzen einer gemeinsam genutzten Bibliothek hinweg zu reduzieren. data
verwendet hat. Das kann viele Probleme verursachen und statische Felder in Vorlagenklassen grundsätzlich nicht zulassen. Insgesamt scheint es, dass selbst in Windows die Dinge nicht so schlecht sind, wie ich dachte, aber ich zögere immer noch, diesen Ansatz zu verwenden, da Template-Instanziierungen immer noch verschiedene vtables und statischen Speicher verwenden. Weiß jemand, wie man dieses Problem vermeidet? Ich habe keine Lösung gefunden.
Ich denke Boost Extension beschäftigt sich genau mit dieser Problemdomäne:
( als Vorbereitung für die Einreichung dieser Bibliothek bei Boost zur Überprüfung )
Besonders interessiert Sie, was der Autor in diesem Blogpost geschrieben hat: "Ressourcenverwaltung über DLL-Grenzen hinweg :
RTTI funktioniert nicht immer über DLL-Grenzen hinweg wie erwartet. Schauen Sie sich die type_info-Klassen an, um zu sehen, wie ich damit umgehen kann.
Ich bin mir nicht sicher, ob seine Lösung wirklich robust ist, aber er hat diesen Gedanken schon einmal gemacht. In der Tat gibt es einige Beispiele, die Boost Extensions verwenden, die Sie ausprobieren können, vielleicht möchten Sie es verwenden.
Tags und Links c++ dll shared-libraries templates cross-platform