2 Bibliotheken vs. eine gleichnamige Klasse
-
Hallo,
ich verwende für ein Projekt 2 Bibliotheken die eine gleichnamige Klasse besitzen (Eventuell mehr als eine!). Das führt anscheinend zu Konflikten.
Wie kann ich das vermeiden?
Ich habe an namespaces gedacht, aber weiss nicht genau, wie meine für eine ganze Bib ein namespace erstellt.Kann mir einer von euch vielleicht helfen?
Ciao,
CL
-
Meistens definieren Bibliotheken aus genau solchen gruenden ihre Klassen in eigenen namespaces, wie die heissen muesstest du der Dokumentation der jeweiligen Bibliothek entnehmen. Wenn du tatsaechlich zwei Bibliotheklen gefunden hast, die so ruecksichtslos waren, mit ihren Klassendefinitionen den globalen Namensraum zuzumuellen, dann koennte es helfen, dir Wrapperklassen zu den fraglichen Klassen zu schreiben und die Header (und damit die deklarationen) dieser Klassen nur in den .cpps deiner Wrapperklassen einzubingen und somit nie mehr als eine der Bibliotheksklassen in einer Uebersetzungseinheit zu haben um den Namenskonflikt zu vermeiden.
-
Da namespaces in C++ offen sind, kann man auch nachträglich Klassen in einen anderen Namespace legen.
Ist aber eh ne sauerei, das ne Lib keinen Namespace benutzt. Wer weiß was noch alles auf einen zu kommt.
-
pumuckl schrieb:
Meistens definieren Bibliotheken aus genau solchen gruenden ihre Klassen in eigenen namespaces, wie die heissen muesstest du der Dokumentation der jeweiligen Bibliothek entnehmen. Wenn du tatsaechlich zwei Bibliotheklen gefunden hast, die so ruecksichtslos waren, mit ihren Klassendefinitionen den globalen Namensraum zuzumuellen, dann koennte es helfen, dir Wrapperklassen zu den fraglichen Klassen zu schreiben und die Header (und damit die deklarationen) dieser Klassen nur in den .cpps deiner Wrapperklassen einzubingen und somit nie mehr als eine der Bibliotheksklassen in einer Uebersetzungseinheit zu haben um den Namenskonflikt zu vermeiden.
Das funktioniert auch nur wirklich bei DLLs und ist allgemein als Hack anzusehen - die ODR gilt hier nämlich trotzdem. Die ORD Verletzung wirkt sich nur bei DLLs nicht aus, auf Grund der Art und Weise wie Windows mit DLLs umgeht. Bei SOs unter Linux würde es AFAIK trotzdem ein Problem geben.
Wenn du das mit LIBs versuchst wirst du draufkommen dass der Linker trotzdem Fehler auswirft oder still und heimlich eine Version der kollidierenden Funktionen/Methoden/Daten verwirft.
Die "saubere Lösung" ist die LIBs zu modifizieren so dass alle Klassen in einem Namespace leben. Andere LIB, anderer Namespace. Bei fertigen LIBs die man bloss verwendet ist das natürlich lästig (vor allem wenn es C libs sind und Funktionsnamen kollidieren), bei LIBs die man selbst schreibt sicher kein Thema, da wie schon erwähnt wurde sowieso jede LIB einen eigenen Namespace haben sollte. Wenn man selbst aus irgendeinem Grund reine C (ohne ++) LIBs bastelt, behilft man sich wohl am besten mit einem gemeinsamen Prefix welches man für alle Funktionen/Daten einer LIB verwendet.
p.S.: es würde funktionieren wenn die kollidierenden Dinge (Funktionen/Daten/...) alle "internal linkage" hätte, bloss die Situation hat man meistens nicht. Ich wüsste z.B. nicht wie man eine Klasse dazu überreden sollte "internal linkage" (für ihre Memberfunktionen etc.) zu haben -- ausser dass man sie in einer Funktion deklariert und definiert. (Kann aber auch nur Unwissenheit meinerseits sein.)
-
Bei dem Problem kann man sich meines Wissens nach folgendermaßen behelfen:
namespace Lib1 { #include "Ein Header der ersten Lib.h" #include "Ein anderer Header der ersten Lib.h" } namespace Lib2 { #include "Header der zweiten Lib etc.h" }
-
Wenn es aber beides Runtime-Bibliotheken sind (DLLs bzw. .so-Dateien) kann es so nicht funktionieren, da der Linker dann die Klassen bzw. Klassenmethoden nicht finden wird (wenn es reine Inline-Definitionen oder aber Template-Klassen sind, dann kann man sie in einen anderen Namespace packen).
Abhilfe schafft hier nur, die beiden Bibliothekenersteller zu verklagen
oder aber mindestens eine DLL vollständig zu wrappen (evtl. viel Arbeit).
-
NES-Spieler schrieb:
Bei dem Problem kann man sich meines Wissens nach folgendermaßen behelfen:
namespace Lib1 { #include "Ein Header der ersten Lib.h" #include "Ein anderer Header der ersten Lib.h" } namespace Lib2 { #include "Header der zweiten Lib etc.h" }Das ginge nur wenn die Bibliotheken alles inline in den Header Files implementiert haben. Plus man bekommt Probleme wenn in "Ein Header der ersten Lib.h" z.B. ein "#include <iostream>" oder sowas steht. Dann hätte man
namespace Lib2 { //#include "Ein Header der ersten Lib.h": //#include <iostream>: namespace std { // ... } }Kann auch nicht gut gehen.