Kampf gegen die ODR möglich?
-
Hallo,
ich verwende DirectX8 und DirectX9 in einem Programm.
Dazu gibt es zwei Klassen (eigene Dateien) in meinem Sourcecode.
Die eine hat die DirectX8 die andere die DirectX9 Library mit pragma includiert.
Nun kommen in beiden Libraries gleichnahmige FUnktionen vor, wodurch der LNK2005 Linkerfehler wegen doppelter Funktionen hochpoppt.Nun habe ich zwei DLL Dateien gebastelt, die die benötigten DX Funktionen durchleiten und lade diese dynamisch nach. Das funktioniert auch tadellos, beide DirectX Versionen sind voll funktionstüchtig, was der Linker zuvor als unmöglich ansieht.
Irgendwie finde ich es ziemlich dämlich, das ich kein Programm kompilieren kann und die Library Funktionen genau den speziellen Klassen zuordnen kann. Generell ist es aber mit der DLL Methode möglich in einem Programm beide gleichnahmige Funktionen im selben Prozessslot zu verwenden.
Es muss doch irgendwie möglich sein die "One Definition Rule" hier genau auf in sich abgeschlossene Klassen korrekt anzuwenden??
Die DX Header Dateien verweisen ja ebenso korrekt auf die jeweiligen Funktionen.Grüße
TheNoName
-
Das einzige, was mir da einfällt, wäre es, die entsprechende Dll explizit zur Laufzeit mittels LoadLibrary nachzuladen. Die benötigten Symbole kann man dann mittels GetProcAddress nachladen. Am Ende entlädt man die Dll wieder und man bekommt keine Probleme mit redundanten Symbolen.
Gruß Kimmi
-
Du meinst die DirectX DLL Dateien anstatt eigener DLL Dateien?
Das wäre nicht möglich, diese exisiteieren je nach Betriebssystem nicht mehr oder heissen anders.
Die Namen der DX Dateien verändert sich am laufenden Bande.
Zum Beispiel ist die D3DX9.dll nun von D3DX9_25 bis D3DX9_42 erhältlich, je nach OS. Ein geziehltes LoadLibrary wird hier genauso dämlich
Die D3DX8.DLL existiert gar nicht mehr.
-
Das hat etwas mit der Gültigkeit von Namen zu tun...
Da spricht ja schon die Bindung der Namen dagegen.Wenn zwei Funktionen die gleiche Signatur haben, dann kann es diese nur einmal je Modul geben und sie muss zwnagsweise auf die selbe externe Funktion verweisen.
Der Linker ist das einfach nicht selektivgenaug, weil er Suchpfade hat und Du ihm nicht explizit sagst, schau dort nach in genau diesem Modul und das nur bei diesem einen Symbol.
Die Isolation über DLLs ist doch OK und vernünftig.
Ich hätte allerdings nicht die originalnamen verwendet sondern meine eigene LIB gebaut mit einem eigenen Interface.
-
Hi,
die Lösung mit den DLL Dateien ist ja funktionstüchtig also habe ich keinen grossen Schmerz damit. Die exportierten Namen sind mit kleinen Anhängen wie DX8 oder DX9 versehen.
Was mich stört ist die Tatsache, das Intellisense den Unterschied deutlich anzeigt, also die unterschiedlichen Headers zu den LIB's erkennt und per "gehe zu Deklaration" auch in die richtigen Headers springt. Es fehlt nur ein Linker Befehl, der einer .cpp sozusagen die eine LIB zuweisst und der anderen .cpp eine andere LIB ohne diese global zu verlinken und dann zu meckern wenn es doppelt vorkommt.
Grüße
TheNoName
-
Du laedst zwei Bibliotheken mit zwei gleichnamigen Funktionen. Wie soll das Betriebssystem entscheiden, welche Implementation dem jeweiligen Namen zugeordnet werden soll. Loesung: Lass es den Programmierer entscheiden mittels LoadLibrary und GetProcAddress. Das ist der gangbare Weg, warum willst du noch einen anderen?
-
Ich habe gerade mal nachgesehen: die Irrlich-Engine löst das mittels expliziten Laden, die unterstützten mehrere Versionen von D3D( version 8 und version 9 ). Also hinkriegen kann man das.
Aber spätestens beim Sprung auf D3D10 oder D3D11 wirst du eh mit einer anderen API konfrontiert, weshalb auch ich den Weg über entsprechende separate Dlls gegangen bin, die die API-Rufe entsprechend kapseln.Gruß Kimmi