Also erstmal: Einen Präprozessor hat Delphi in dem Sinne nicht. Aber speziell zu deinem Problem:
Die Units in Delphi sind zweigeteilt. Oben ist der Interface Abschnitt und unten ist der Implementation Abschnitt. Hierbei kann der Interface Abschnitt mit dem Header in C(++) verglichen werden und der Implementation Abschnitt mit der .cpp Datei. Der Interface Abschnitt enthält alle nach aussen (also öffentlichen) Deklarationen, Prototypen, Typen, Konstanten, Variablen, etc. Wenn in diesem Abschnitt eine Deklaration/Typ, etc aus einer anderen
Unit gebraucht wird, dann muss diese in die uses Liste im Interface Abschnitt eingebunden werden. Alle anderen Units, welche u.a. auch erst zur Implementation genutzt werden, sollten in den Implementation Abschnitt eingefügt werden. Ist ja in der .h/.cpp Aufteilung ja nicht anders mit den #Include Anweisungen.
Von daher zur Lösung: Binde bei zirkulären
Unit Referenzen in einer
Unit die jeweils andere im Implementation Abschnitt ein anstatt im Interface Abschnitt. Eine andere Lösung kennt Delphi hier grundlegend nicht. In manchen Fällen, wo dies sonst nicht möglich ist, wären zwei Lösungen machbar:
1. Beide Units in einer Zusammenfassen
2. Im Interface Abschnitt den Prototypen so deklarieren, dass er einen Basistypen oder Vorgängerklasse referenziert. In der Implementierung dann der Cast mit Prüfung, weil im Implementation Abschnitt kann dann ja die spezielle Implementierung angezogen werden.
Beispiel für 2.: oben den Prototypen mit der Klasse TObject deklarieren und dann den Cast in der Implementierung. Alternativ, wenn es um Klassen geht, eine (abstrakte) Basisklasse einführen in einer 3.
Unit, welche dann von beiden Units referenziert werden kann.