1

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?

Thomas O
  • 6,026
  • 12
  • 42
  • 60
  • 2
    Try moving the `RCLowPass` unit in the uses of the `Unit2` to the implementation part of the `Unit2` unit. – RRUZ Jul 05 '11 at 08:12
  • 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 Jul 05 '11 at 08:14
  • @RRUZ Now I am getting: `[DCC Error] RCLowPass.pas(29): E2096 Method identifier expected` for `TForm2.Prop1Name.Caption := 'R1'` and related lines. – Thomas O Jul 05 '11 at 08:15
  • @David: My error. Overzealous editing - I removed the `use` clause. – Thomas O Jul 05 '11 at 08:16
  • @Thomas Your code doesn't even compile. There needs to be an `implementation` in `Unit2`. And why are you throwing an error relating to `TForm2` at us? We can't see `TForm2`. Please step back, slow down, and put together a short example that illustrates your problem. – David Heffernan Jul 05 '11 at 08:17
  • @David I didn't want to post the entire 3-4 pages of code, so I edited it. Obviously, too much... – Thomas O Jul 05 '11 at 08:21
  • @Thomas remove the `RCLowPass` unit from uses part of the interface of the `Unit2` (just let the `RCLowPass` unit in the implementation part) and then in the `RCLowPass` unit move the `Unit2` unit to the implementation part. – RRUZ Jul 05 '11 at 08:23
  • @RRUZ it is still complaining about a `method identifier expected`. Perhaps I am not assigning the values to the labels properly? – Thomas O Jul 05 '11 at 08:30
  • Ah, problem solved - I was assigning to the type `TForm2` not the object `Form2`. @RRUZ, why don't you make your comment an answer so you can get credit for it. – Thomas O Jul 05 '11 at 08:34
  • 2
    @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 http://stackoverflow.com/questions/2644973/getting-around-circular-references-in-delphi and http://stackoverflow.com/questions/6579602/avoiding-a-circular-reference-in-delphi, so I think which is better if you delete this question :) – RRUZ Jul 05 '11 at 08:45
  • @RRUZ: did you realize that you built a circular reference into your links? – jpfollenius Jul 05 '11 at 09:57
  • @Smasher, Oops you are right. – RRUZ Jul 05 '11 at 10:06
  • @RRUZ: Actually, I find that very appropriate for this question. – jpfollenius Jul 05 '11 at 10:13
  • @Thomas O: your code doesn't even compile because it has `RCLowPass` both int the interface and implementation section (Unit 2). – jpfollenius Jul 05 '11 at 10:14
  • 1
    @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 Jul 05 '11 at 12:19

1 Answers1

4
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;
  ...
Ravaut123
  • 2,764
  • 31
  • 46
  • 1
    This answer looks dubious to me. Looking at the code and the names, I'd expect RCLowPass, the code with the low-pass filter, to have no UI code in it. And Unit2 should have a reference to RCLowPass, and all the UI code. In other words there should probably be no reference from RCLowPass to Unit2. – David Heffernan Jul 05 '11 at 12:18
  • 1
    Not the answer but the code is dubious. First don't set a specific Form in the unit of RCLowPass. Set a Filter property. – Ravaut123 Jul 05 '11 at 13:28
  • Set a Filter property in unit2.TForm2 that do the SelectRCLowPassFilter. If SelectRCLowPassFilter is made for more than one form then set the procedure in a new unit with a value of your base form. But if the procedure is only for the form (unit2.TForm2), then set the procedure in the form as private. – Ravaut123 Jul 05 '11 at 13:40
  • In unit2 is RCLowPass declared twice, remove it in the implementation uses – Ravaut123 Jul 05 '11 at 13:44