Recent

Author Topic: Namespaces UNIT1 does not see unit2  (Read 2611 times)

jcaser1948

  • Jr. Member
  • **
  • Posts: 68
Namespaces UNIT1 does not see unit2
« on: September 02, 2020, 05:33:03 pm »
I try to convert an old Pascal program into Lazarus (The "Dinning Philosophers").I have made a very simple formular with a botton and a Memo. I intended to show the "writtels" in Memo1.
The problem is that Unit1, where the formular resides, does not see the Procedures in UNIT2 .
I have tried another version and put all procedures together in an Unit, but also to no avail.
I know this is a problem with namespaces, but I seek a simple solution What do I wrong?.Is there a simple solution without rewriting everything?
I Attach the code for the two units
Thanks in advance
Code: Pascal  [Select][+][-]
  1.  unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, SyncObjs, Dialogs, StdCtrls,Unit2;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.    // Button1: TButton;
  16.    // Memo1: TMemo;
  17.      procedure Button1Click(Sender: TObject);
  18.      private
  19.      protected
  20.  
  21.     public
  22.  
  23.     // procedure Button1Click(Sender: TObject);
  24.   end;
  25.  
  26.  
  27. var
  28.  
  29.   Form1: TForm1;
  30.   Memo1: TMemo;
  31.   Button1: TButton;
  32.  
  33. implementation
  34.  
  35.  
  36. {$R *.lfm}
  37.  
  38.  
  39. { TForm1 }
  40.  
  41.  procedure TForm1.Button1Click(Sender: TObject);
  42. begin
  43.  Randomize;
  44.  DinnerBegin;
  45.  WaitForDinnerOver;
  46. end;
  47.  
  48.  
  49. end.
  50.    unit Unit2;
  51.  
  52. {$mode objfpc}{$H+}
  53.  
  54. interface
  55.  
  56. uses
  57.   Classes, SysUtils, SyncObjs;
  58.   const
  59.   PHIL_COUNT   = 5;
  60.   LIFESPAN     = 7;
  61.   DELAY_RANGE  = 950;
  62.   DELAY_LOW    = 50;
  63.   PHIL_NAMES: array[1..PHIL_COUNT] of string = ('Aristotle', 'Kant', 'Spinoza', 'Marx', 'Russell');
  64.  
  65.   type
  66.   TFork  = TCriticalSection;
  67.   TPhilosopher = class;
  68.  
  69.   var
  70.   Forks: array[1..PHIL_COUNT] of TFork;
  71.   Philosophers: array[1..PHIL_COUNT] of TPhilosopher;
  72.  type
  73.   TPhilosopher = class(TThread)
  74.   private
  75.    FName: string;
  76.    FFirstFork, FSecondFork: TFork;
  77.   protected
  78.     procedure Execute; override;
  79.   public
  80.  
  81.     constructor Create(const aName: string; aForkIdx1, aForkIdx2: Integer);
  82.   end;
  83. implementation
  84. Uses Unit1;
  85. constructor TPhilosopher.Create(const aName: string; aForkIdx1, aForkIdx2: Integer);
  86. begin
  87.  inherited Create(True);
  88.  FName := aName;
  89.  if aForkIdx1 < aForkIdx2 then
  90.    begin
  91.      FFirstFork := Forks[aForkIdx1];
  92.      FSecondFork := Forks[aForkIdx2];
  93.    end
  94.  else
  95.    begin
  96.      FFirstFork := Forks[aForkIdx2];
  97.      FSecondFork := Forks[aForkIdx1];
  98.    end;
  99. end;
  100.  
  101.  
  102. procedure TPhilosopher.Execute;
  103. var
  104.  LfSpan: Integer = LIFESPAN;
  105. begin
  106.  while LfSpan > 0 do
  107.    begin
  108.      Dec(LfSpan);
  109.      Memo1.Lines.Clear;  //delete all lines of Memo1
  110.      Memo1.Lines.Add('This is the first line.');     //add a line
  111.      WriteLn(FName, ' sits down at the table');
  112.      FFirstFork.Acquire;
  113.      FSecondFork.Acquire;
  114.      WriteLn(FName, ' eating');
  115.      Sleep(Random(DELAY_RANGE) + DELAY_LOW);
  116.      FSecondFork.Release;
  117.      FFirstFork.Release;
  118.  
  119.      WriteLn(FName, ' is full and leaves the table');
  120.      if LfSpan = 0 then
  121.        continue;
  122.      WriteLn(FName, ' thinking');
  123.      Sleep(Random(DELAY_RANGE) + DELAY_LOW);
  124.      WriteLn(FName, ' is hungry');
  125.    end;
  126. end;
  127.  
  128.  
  129. procedure DinnerBegin;
  130. var
  131.  I: Integer;
  132.  Phil: TPhilosopher;
  133. begin
  134.  for I := 1 to PHIL_COUNT do
  135.    Forks[I] := TFork.Create;
  136.  for I := 1 to PHIL_COUNT do
  137.    Philosophers[I] := TPhilosopher.Create(PHIL_NAMES[I], I, Succ(I mod PHIL_COUNT));
  138.  for Phil in Philosophers do
  139.    Phil.Start;
  140. end;
  141.  
  142.  
  143. procedure WaitForDinnerOver;
  144. var
  145.  Phil: TPhilosopher;
  146.  Fork: TFork;
  147. begin
  148.  for Phil in Philosophers do
  149.    begin
  150.      Phil.WaitFor;
  151.      Phil.Free;
  152.    end;
  153.  for Fork in Forks do
  154.    Fork.Free;
  155. end;
  156.  
  157.  
  158.  
  159.  
  160. end.                

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: Namespaces UNIT1 does not see unit2
« Reply #1 on: September 02, 2020, 06:01:00 pm »
For any items like types constants, procedures, functions etc must show in the INTERFACE section of the unit

 with regards to Procedures and Functions, Only the Header part is to be placed in the Interface section, not the body of the code.

 When doing this the compiler will find the functions there.
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: Namespaces UNIT1 does not see unit2
« Reply #2 on: September 02, 2020, 06:03:34 pm »
I try to convert an old Pascal program into Lazarus (The "Dinning Philosophers").I have made a very simple formular with a botton and a Memo. I intended to show the "writtels" in Memo1.
The problem is that Unit1, where the formular resides, does not see the Procedures in UNIT2 .
I have tried another version and put all procedures together in an Unit, but also to no avail.
I know this is a problem with namespaces, but I seek a simple solution What do I wrong?.Is there a simple solution without rewriting everything?
I Attach the code for the two units
Thanks in advance
Code: Pascal  [Select][+][-]
  1.  unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, SyncObjs, Dialogs, StdCtrls,Unit2;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.    // Button1: TButton;
  16.    // Memo1: TMemo;
  17.      procedure Button1Click(Sender: TObject);
  18.      private
  19.      protected
  20.  
  21.     public
  22.  
  23.     // procedure Button1Click(Sender: TObject);
  24.   end;
  25.  
  26.  
  27. var
  28.  
  29.   Form1: TForm1;
  30.   Memo1: TMemo;
  31.   Button1: TButton;
  32.  
  33. implementation
  34.  
  35.  
  36. {$R *.lfm}
  37.  
  38.  
  39. { TForm1 }
  40.  
  41.  procedure TForm1.Button1Click(Sender: TObject);
  42. begin
  43.  Randomize;
  44.  DinnerBegin;
  45.  WaitForDinnerOver;
  46. end;
  47.  
  48.  
  49. end.
  50.    unit Unit2;   // REMOVE THIS From HERE TOOOOLOOOOO.....
  51.  
  52. {$mode objfpc}{$H+}
  53.  
  54. interface
  55.  
  56. uses
  57.   Classes, SysUtils, SyncObjs;
  58.   const
  59.   PHIL_COUNT   = 5;
  60.   LIFESPAN     = 7;
  61.   DELAY_RANGE  = 950;
  62.   DELAY_LOW    = 50;
  63.   PHIL_NAMES: array[1..PHIL_COUNT] of string = ('Aristotle', 'Kant', 'Spinoza', 'Marx', 'Russell');
  64.  
  65.   type
  66.   TFork  = TCriticalSection;
  67.   TPhilosopher = class;
  68.  
  69.   var
  70.   Forks: array[1..PHIL_COUNT] of TFork;
  71.   Philosophers: array[1..PHIL_COUNT] of TPhilosopher;
  72.  type
  73.   TPhilosopher = class(TThread)
  74.   private
  75.    FName: string;
  76.    FFirstFork, FSecondFork: TFork;
  77.   protected
  78.     procedure Execute; override;
  79.   public
  80.  
  81.     constructor Create(const aName: string; aForkIdx1, aForkIdx2: Integer);
  82.   end;
  83. implementation
  84. Uses Unit1;
  85. constructor TPhilosopher.Create(const aName: string; aForkIdx1, aForkIdx2: Integer);
  86. begin
  87.  inherited Create(True);
  88.  FName := aName;
  89.  if aForkIdx1 < aForkIdx2 then
  90.    begin
  91.      FFirstFork := Forks[aForkIdx1];
  92.      FSecondFork := Forks[aForkIdx2];
  93.    end
  94.  else
  95.    begin
  96.      FFirstFork := Forks[aForkIdx2];
  97.      FSecondFork := Forks[aForkIdx1];
  98.    end;
  99. end;
  100.  
  101.  
  102. procedure TPhilosopher.Execute;
  103. var
  104.  LfSpan: Integer = LIFESPAN;
  105. begin
  106.  while LfSpan > 0 do
  107.    begin
  108.      Dec(LfSpan);
  109.      Memo1.Lines.Clear;  //delete all lines of Memo1
  110.      Memo1.Lines.Add('This is the first line.');     //add a line
  111.      WriteLn(FName, ' sits down at the table');
  112.      FFirstFork.Acquire;
  113.      FSecondFork.Acquire;
  114.      WriteLn(FName, ' eating');
  115.      Sleep(Random(DELAY_RANGE) + DELAY_LOW);
  116.      FSecondFork.Release;
  117.      FFirstFork.Release;
  118.  
  119.      WriteLn(FName, ' is full and leaves the table');
  120.      if LfSpan = 0 then
  121.        continue;
  122.      WriteLn(FName, ' thinking');
  123.      Sleep(Random(DELAY_RANGE) + DELAY_LOW);
  124.      WriteLn(FName, ' is hungry');
  125.    end;
  126. end;
  127.  
  128.  
  129. procedure DinnerBegin;
  130. var
  131.  I: Integer;
  132.  Phil: TPhilosopher;
  133. begin
  134.  for I := 1 to PHIL_COUNT do
  135.    Forks[I] := TFork.Create;
  136.  for I := 1 to PHIL_COUNT do
  137.    Philosophers[I] := TPhilosopher.Create(PHIL_NAMES[I], I, Succ(I mod PHIL_COUNT));
  138.  for Phil in Philosophers do
  139.    Phil.Start;
  140. end;
  141.  
  142.  
  143. procedure WaitForDinnerOver;
  144. var
  145.  Phil: TPhilosopher;
  146.  Fork: TFork;
  147. begin
  148.  for Phil in Philosophers do
  149.    begin
  150.      Phil.WaitFor;
  151.      Phil.Free;
  152.    end;
  153.  for Fork in Forks do
  154.    Fork.Free;
  155. end;
  156.  
  157.  
  158.  
  159.  
  160. end.                

Look at  my comment about removing a display Unit define in your code above
The only true wisdom is knowing you know nothing

jcaser1948

  • Jr. Member
  • **
  • Posts: 68
Re: Namespaces UNIT1 does not see unit2
« Reply #3 on: September 02, 2020, 06:09:27 pm »
It compiles!!!!! Thank you very much

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Namespaces UNIT1 does not see unit2
« Reply #4 on: September 02, 2020, 06:38:20 pm »
I try to convert an old Pascal program into Lazarus (The "Dinning Philosophers")...
Why do you think the program is old?
IIRC, it should be dated around April 2019.

jcaser1948

  • Jr. Member
  • **
  • Posts: 68
Re: Namespaces UNIT1 does not see unit2
« Reply #5 on: September 02, 2020, 06:41:01 pm »
Jamie Where is your Comment about removing a display Unit define in my code above. I could not find it.
Moreover I have another problem. The Program compiles ,but I get an exception EclassNotFound with the message TMemo not found.
But I have  Memo1: TMemo;    declared in var.
Sorry

jcaser1948

  • Jr. Member
  • **
  • Posts: 68
Re: Namespaces UNIT1 does not see unit2
« Reply #6 on: September 02, 2020, 06:49:21 pm »
Thanks for your answer AVk.
I thought the program was old because i did not find any datum it did not have any Formular whatsoever.
You can not expect those days anyone opening a Windows Powershell to see the results of the program.It wonders me that it is so new
« Last Edit: September 03, 2020, 04:52:50 pm by jcaser1948 »

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Namespaces UNIT1 does not see unit2
« Reply #7 on: September 02, 2020, 07:07:29 pm »
The program comes from Rosetta Code, right? In any case, it was written specifically for Rosetta Code.
By the way, there one can always look into history.
Hmm, I was wrong. The program is dated March 2019.

jcaser1948

  • Jr. Member
  • **
  • Posts: 68
Re: Namespaces UNIT1 does not see unit2
« Reply #8 on: September 02, 2020, 07:31:09 pm »
Yes Avk.The program comes from Rosetta Code. I thought it was an easy example to see how the semaphores in the SyncObjs Unit. What I did not anticipate was the trouble with the Namespaces and the Procedures and Variables of the two units not seeing each other. Well at the moment I hope for a hint why I can not see in the second Unit  the Memo declared in the first unit. Probably is something very silly, but at the moment beyond my scope

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Namespaces UNIT1 does not see unit2
« Reply #9 on: September 02, 2020, 07:58:35 pm »
You can have two units in your project.
However, to show text in a memo (GUI) updated from a thread you need to adapt your code that relies on WriteLn.
See the attached project.

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Namespaces UNIT1 does not see unit2
« Reply #10 on: September 02, 2020, 08:10:40 pm »
To see in a unit (let's call it unit A) any object/var/procedure/function/etc. declared in another (unit B) there are two basic requisites:

1) The identifier must be declared in the interface section of unit B
2) Unit B must be in one of the (interface/implementation) uses clauses of unit A.

Now comes a problem: when unit A uses unit B and unit B uses unit A. In that case, one of them must use the other in the implementation while the other uses the first in the interface; otherwise you'll cause a circular reference which cannot be resolved by the compiler.

Most of this is explained in the Reference Manual (mainly in chapter 16, section 16.4: Unit dependencies).

Another problem arises when unit B tries to use an object from unit A whose class is declared in yet another unit: you must add to the uses clause of unit B that third unit in which the class is declared (for example, for TMemo that is StdCtrls); otherwise unit B won't "know" the properties/methods/etc. of the class/object (hence the message: "class TMemo not found").

That's very basically all there is to it; there is quite a lot more info in the reference manual. HTH!
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: Namespaces UNIT1 does not see unit2
« Reply #11 on: September 02, 2020, 11:14:07 pm »
Jamie Where is your Comment about removing a display Unit define in my code above. I could not find it.
Moreover I have another problem. The Program compiles ,but I get an exception EclassNotFound with the message TMemo not found.
But I have  Memo1: TMemo;    declared in var.
Sorry

Look at line 50 of your quoted code I have in the response.
The only true wisdom is knowing you know nothing

jcaser1948

  • Jr. Member
  • **
  • Posts: 68
Re: Namespaces UNIT1 does not see unit2
« Reply #12 on: September 03, 2020, 04:34:48 pm »
Thanks Howard PC. Your program works perfectly. I´m still chewing on the code. Perhaps you could send this modified code to Rosseta Code, so they may have a proper modern Lazarus program as muster.
Thanks again tu you and to everyone involved

jcaser1948

  • Jr. Member
  • **
  • Posts: 68
Re: Namespaces UNIT1 does not see unit2
« Reply #13 on: September 03, 2020, 04:39:20 pm »
Thak Lucamar for your hint.
 I have tried to find the Reference Manual (chapter 16, section 16.4: Unit dependencies), but I went lost in the numerous Lazarus documentation.
Perhaps you could give me a direct link
Thanks again

jcaser1948

  • Jr. Member
  • **
  • Posts: 68
Re: Namespaces UNIT1 does not see unit2
« Reply #14 on: September 03, 2020, 05:39:10 pm »
howardpc
Thanks again. I am chewing the code and I think I understand it. However, What is the meaning of
 Synchronize(@ShowInMainThread); I thought the synchronisation was already given by  syncobjs?.And what is the meaning of @ in ShowInMainThread?
Thanks again

 

TinyPortal © 2005-2018