Ich habe eine zirkuläre Abhängigkeit zwischen zwei Funktionen. Ich möchte, dass jede dieser Funktionen in einer eigenen DLL liegt. Ist es möglich, dies mit Visual Studio zu erstellen?
%Vor%- & gt; sollte in foo.dll
kompilieren %Vor%- & gt; sollte in bar.dll
kompilierenIch habe zwei Projekte im Visual Studio erstellt, eins für foo und eins für bar. Indem ich mit den 'Referenzen' gespielt und einige Male kompiliert habe, habe ich es geschafft, die DLLs zu bekommen, die ich möchte. Ich würde jedoch gerne wissen, ob Visual Studio eine Möglichkeit bietet, dies auf eine saubere Art und Weise zu tun.
Wenn foo sich ändert, muss bar nicht neu kompiliert werden, weil ich nur von der Signatur von bar abhängig bin, nicht von der Implementierung von bar. Wenn beide DLLs die lib vorhanden haben, kann ich neue Funktionen in beide kompilieren und das ganze System funktioniert immer noch.
Der Grund, warum ich das versuche, ist, dass ich ein Altsystem mit zirkulären Abhängigkeiten habe, das derzeit statisch verknüpft ist. Wir wollen aus verschiedenen Gründen auf dlls zugehen. Wir wollen nicht warten, bis wir alle zirkulären Abhängigkeiten aufgeräumt haben. Ich habe über Lösungen nachgedacht und einige Sachen mit gcc auf Linux ausprobiert und dort ist es möglich zu tun, was ich vorschlage. So können Sie zwei gemeinsam genutzte Bibliotheken haben, die voneinander abhängig sind und unabhängig voneinander erstellt werden können.
Ich weiß, dass zirkuläre Abhängigkeiten nicht gut sind, aber das ist nicht die Diskussion, die ich haben möchte.
Der Grund, warum es auf Unix-ähnlichen Systemen funktioniert, ist, dass sie die tatsächliche Verbindungsauflösung zur Ladezeit durchführen. Eine gemeinsam genutzte Bibliothek weiß nicht, woher ihre Funktionsdefinition kommt, bis sie in einen Prozess geladen wird. Der Nachteil davon ist, dass Sie es auch nicht wissen. Eine Bibliothek kann Funktionen in jeder anderen Bibliothek finden und aufrufen (oder sogar in der Hauptbinärdatei, die den Prozess gestartet hat). Außerdem wird standardmäßig alles in einer gemeinsam genutzten Bibliothek exportiert.
Windows funktioniert überhaupt nicht so. Nur explizit exportierte Objekte werden exportiert, und alle Importe müssen zur Bibliotheksverbindungszeit aufgelöst werden. Zu diesem Zeitpunkt wurde die Identität der DLL ermittelt, die jede importierte Funktion bereitstellt. Dies erfordert eine Importbibliothek, mit der verlinkt werden kann.
Allerdings kann man dies (mit etwas Zusatzarbeit) umgehen. Verwenden Sie LoadLibrary
, um eine beliebige DLL zu öffnen, und verwenden Sie dann GetProcAddress
, um die Funktionen zu finden, die Sie aufrufen möchten. Auf diese Weise gibt es keine Einschränkungen. Aber die Einschränkungen in der normalen Methode gibt es aus einem bestimmten Grund.
Wenn Sie von statischen Bibliotheken zu DLLs wechseln wollen, klingt es so, als würden Sie davon ausgehen, dass Sie jede statische Bibliothek zu einer DLL machen sollten. Das ist nicht deine einzige Option. Warum fangen Sie nicht an, Code nur dann in DLLs zu verschieben, wenn Sie ihn als eigenständiges Modul identifizieren, das in ein mehrschichtiges Design ohne Zirkularität passt? Auf diese Weise können Sie den Prozess jetzt beginnen, aber immer noch Stück für Stück angreifen.
Ich habe tiefe Sympathie mit Ihrer Situation (wie durch Ihre Bearbeitung klargestellt wurde), aber als ein überzeugter Anhänger davon, das Richtige zu tun, nicht das, was jetzt funktioniert , wenn es überhaupt eine Möglichkeit gibt Ich denke, Sie müssen diese Projekte refaktorieren .
Beheben Sie das Problem nicht das Symptom.
Es ist möglich, das LIB-Dienstprogramm mit .EXP-Dateien zu verwenden, um eine Reihe von DLLs mit einem Zirkelverweis wie diesem zu "bootstrappen" (Build ohne vorherige .LIB-Dateien). Weitere Informationen finden Sie im MSDN-Artikel .
Ich stimme mit anderen darüber überein, dass diese Art von Situation vermieden werden sollte, indem das Design überarbeitet wird.
Es ist nicht möglich, sauber zu machen. Weil beide voneinander abhängen, wenn A sich ändert, muss B neu kompiliert werden. Weil B neu kompiliert wurde, hat es sich geändert und A muss neu kompiliert werden und so weiter.
Das ist Teil des Grundes, warum zirkuläre Abhängigkeiten schlecht sind und ob Sie wollen oder nicht, Sie können das nicht aus der Diskussion herauslassen.
Visual Studio erzwingt im Allgemeinen Abhängigkeiten, da sich die Funktionsadressen innerhalb der neu kompilierten DLL ändern können. Auch wenn die Signatur identisch sein kann, kann sich die exponierte Adresse ändern.
Wenn Sie jedoch feststellen, dass Visual Studio in der Regel die gleichen Funktionsadressen zwischen den Builds verwaltet, können Sie eine der Buildeinstellungen für "Nur Projekt" verwenden (ignoriert Abhängigkeiten). Wenn Sie dies tun und eine Fehlermeldung erhalten, dass die Abhängigkeits-DLL nicht geladen werden kann, erstellen Sie beide einfach neu.
Sie müssen die zwei DLLs entkoppeln, die Schnittstellen und die Implementierung in zwei verschiedene DLLs platzieren und dann die späte Bindung verwenden, um die Klasse zu instanziieren.
%Vor% %Vor% %Vor% %Vor%Die "Factory" -Klassen sind technisch nicht notwendig, aber es ist viel schöner zu sagen:
%Vor%im Anwendungscode als:
%Vor%aus folgenden Gründen:
- Kenneth Kasajian
Der einzige Weg, wie Sie das "sauber" umgehen (und ich verwende den Begriff lose), besteht darin, eine der statischen / Verbindungszeitabhängigkeiten zu eliminieren und sie in eine Laufzeitabhängigkeit umzuwandeln.
Vielleicht in etwa so:
%Vor%Foo.dll wird die Funktion exportieren. Bar.dll versucht nicht länger, die Funktion zu importieren; Stattdessen löst es die Funktionsadresse zur Laufzeit auf.
Rollen Sie Ihre eigenen Fehlerbehandlung und Leistungsverbesserungen.
Tags und Links c++ dll circular-dependency