1
votes

I have a unit called RCLowPass which uses Unit2. It uses the object TForm2.

Unit2 also uses RCLowPass.

Delphi complains about a circular reference because one module requires the other.

Below are relevant samples of the units in question.

RCLowPass:

unit RCLowPass;

interface

uses
  ComplexMath, ExtraMath, Unit2;

procedure SelectRCLowPassFilter;

implementation

{ This is why I need Unit2. }
procedure SelectRCLowPassFilter;
begin
  // Setup form for RC Low Pass
  TForm2.Prop1Name.Caption := 'R1';
  TForm2.Prop1Name.Visible := true;
  TForm2.Prop2Name.Caption := 'C1';
  TForm2.Prop2Name.Visible := true;
  TForm2.Prop3Name.Visible := false;
  TForm2.Prop4Name.Visible := false;
  TForm2.Prop5Name.Visible := false;
  TForm2.Prop6Name.Visible := false;
  TForm2.Prop7Name.Visible := false;
  TForm2.Prop8Name.Visible := false;
  TForm2.Prop1Value.Visible := true;
  TForm2.Prop2Value.Visible := true;
  TForm2.Prop3Value.Visible := false;
  TForm2.Prop4Value.Visible := false;
  TForm2.Prop5Value.Visible := false;
  TForm2.Prop6Value.Visible := false;
  TForm2.Prop7Value.Visible := false;
  TForm2.Prop8Value.Visible := false;
end;

end.

Unit2:

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, RCLowPass, ExtCtrls;

var
  Form2: TForm2;

implementation

uses RCLowPass;

{$R *.dfm}

{ This is why I need RCLowPass. }
procedure TForm2.Button1Click(Sender: TObject);
var
  v : real;
begin
  ShowMessage('Output of RC lowpass with R=1k, C=100n');
  v := RCLowPassZAtFreq(1000, 100e-9, 10);
  ShowMessage('@10Hz: ' + FormatFloat('#.########', v));
  v := RCLowPassZAtFreq(1000, 100e-9, 10);
  ShowMessage('@20Hz: ' + FormatFloat('#.########', v));
  v := RCLowPassZAtFreq(1000, 100e-9, 20);
  ShowMessage('@50Hz: ' + FormatFloat('#.########', v));
  v := RCLowPassZAtFreq(1000, 100e-9, 50);
  ShowMessage('@100Hz: ' + FormatFloat('#.########', v));
  v := RCLowPassZAtFreq(1000, 100e-9, 100);
  ShowMessage('@200Hz: ' + FormatFloat('#.########', v));
  v := RCLowPassZAtFreq(1000, 100e-9, 200);
  ShowMessage('@500Hz: ' + FormatFloat('#.########', v));
  v := RCLowPassZAtFreq(1000, 100e-9, 500);
  ShowMessage('@1000Hz: ' + FormatFloat('#.########', v));
  v := RCLowPassZAtFreq(1000, 100e-9, 1000);
  ShowMessage('@2000Hz: ' + FormatFloat('#.########', v));
  v := RCLowPassZAtFreq(1000, 100e-9, 2000);
  ShowMessage('@5000Hz: ' + FormatFloat('#.########', v));
  v := RCLowPassZAtFreq(1000, 100e-9, 5000);
  ShowMessage('@10000Hz: ' + FormatFloat('#.########', v));
end;

procedure SelectFilter(filter : integer);
begin
  if filter = 0 then
    SelectRCLowPassFilter();
end;

end.

How can I fix the circular reference?

1
Try moving the RCLowPass unit in the uses of the Unit2 to the implementation part of the Unit2 unit. - RRUZ
Your example is defective because there are no circular references. It's not possible to advise you since you haven't made it clear why, in the real code, RCLowPass uses Unit2 in the interface section of RCLowPass. - David Heffernan
@RRUZ Now I am getting: [DCC Error] RCLowPass.pas(29): E2096 Method identifier expected for TForm2.Prop1Name.Caption := 'R1' and related lines. - Thomas O
@Thomas, this question is too specific, I don't know if will help to somebody else in the future. in S.O exist more general questions about circular references like stackoverflow.com/questions/2644973/… and stackoverflow.com/questions/6579602/…, so I think which is better if you delete this question :) - RRUZ
@Thomas I'd strongly recommend that you move the UI code out of the RCLowPass unit that does the filter, and keep it all in Unit2. - David Heffernan

1 Answers

4
votes
unit RCLowPass;
interface

uses
  ComplexMath, ExtraMath;

procedure SelectRCLowPassFilter;

implementation
uses
  Unit2; // <<-- HERE

{ This is why I need Unit2. }
procedure SelectRCLowPassFilter;
begin
  // Setup form for RC Low Pass
  TForm2.Prop1Name.Caption := 'R1';
  TForm2.Prop1Name.Visible := true;
  ...