Recent

Author Topic: external module connection error  (Read 5675 times)

sunjob

  • New Member
  • *
  • Posts: 28
external module connection error
« on: April 13, 2024, 02:08:04 am »
good day!

initial data:
prj1.lpr - lazarus cli application
parser.pas - external module
fpc-3.2.2 & lazarus-2.2.6/3.2.0 (does not affect the error)

the module is supposed to use command line argument parser functions
on module:
Code: Pascal  [Select][+][-]
  1. uses CustApp

as long as functions are not called (empty module) - assembly without errors
a function call produces an error
Code: Pascal  [Select][+][-]
  1. hasOption('h', 'help');
  2. -->
  3. parser.pas(16,1) Error: Identifier not found "hasOption"
  4.  

on main-module - w/o error
prj1.lpr
Code: Pascal  [Select][+][-]
  1. program prj1;
  2. {$mode objfpc}{$H+}
  3. uses
  4.   {$IFDEF UNIX}
  5.   cthreads,
  6.   {$ENDIF}
  7.   Classes, SysUtils, CustApp, LazFileUtils, parser;
  8.  
  9. type
  10.   app = class(TCustomApplication)
  11.   protected
  12.   procedure   DoRun; override;
  13.   public
  14.   constructor Create(TheOwner : TComponent); override;
  15.   destructor  Destroy;                       override;
  16.   end;
  17.  
  18. procedure app.DoRun;
  19. begin
  20. hasOption('h', 'help'); // uses CustApp
  21. Terminate;
  22. end;
  23.  
  24. constructor app.Create(TheOwner : TComponent);
  25. begin
  26. inherited Create(TheOwner);
  27. StopOnException := True;
  28. end;
  29.  
  30. destructor app.Destroy;
  31. begin
  32. inherited Destroy;
  33. end;
  34.  
  35. var Application : app;
  36. {$R *.res}
  37. begin
  38. Application       := app.Create(nil);
  39. Application.Title := 'app';
  40. Application.Run;
  41. Application.Free;
  42. end.

parser.pas
Code: Pascal  [Select][+][-]
  1. unit parser;
  2. interface
  3. {$mode objfpc}{$H+}
  4. uses
  5.   {$IFDEF UNIX}
  6.   cthreads,
  7.   {$ENDIF}
  8.   Classes, SysUtils, CustApp;
  9.  
  10. procedure proc;
  11.  
  12. implementation
  13.  
  14. procedure proc;
  15. begin
  16. //hasOption('h', 'help'); // uses CustApp
  17. end;
  18.  
  19. initialization
  20. finalization
  21. end.
« Last Edit: April 13, 2024, 04:40:05 am by sunjob »

TRon

  • Hero Member
  • *****
  • Posts: 2684
Re: external module connection error
« Reply #1 on: April 13, 2024, 04:11:59 am »
Hasoption is a method of TCustomApplication, see also here and as such can not be used in a general procedure unless accessing the customappliction instance.

This is OOP basics.

sunjob

  • New Member
  • *
  • Posts: 28
Re: external module connection error
« Reply #2 on: April 13, 2024, 04:38:39 am »
ok, check this mod? To what extent will “this implementation” be correct? thank!!!
prj
Code: Pascal  [Select][+][-]
  1. program prj1;
  2. {$mode objfpc}{$H+}
  3. uses
  4.   {$IFDEF UNIX}
  5.   cthreads,
  6.   {$ENDIF}
  7.   Classes, SysUtils, CustApp, LazFileUtils, parser;
  8.  
  9. type
  10.   app = class(TCustomApplication)
  11.   protected
  12.   procedure   DoRun; override;
  13.   public
  14.   constructor Create(TheOwner : TComponent); override;
  15.   destructor  Destroy;                       override;
  16.   end;
  17.  
  18. var Application : app;
  19.  
  20. procedure app.DoRun;
  21. begin
  22. parser.init(Application);
  23. parser.proc;
  24. Terminate;
  25. end;
  26.  
  27. constructor app.Create(TheOwner : TComponent);
  28. begin
  29. inherited Create(TheOwner);
  30. StopOnException := True;
  31. end;
  32.  
  33. destructor app.Destroy;
  34. begin
  35. inherited Destroy;
  36. end;
  37.  
  38. //var Application : app;
  39. {$R *.res}
  40. begin
  41. Application       := app.Create(nil);
  42. Application.Title := 'app';
  43. Application.Run;
  44. Application.Free;
  45. end.
  46.  

parser
Code: Pascal  [Select][+][-]
  1. unit parser;
  2. interface
  3. {$mode objfpc}{$H+}
  4. uses
  5.   {$IFDEF UNIX}
  6.   cthreads,
  7.   {$ENDIF}
  8.   Classes, SysUtils, CustApp;
  9.  
  10. procedure init(p:TCustomApplication);
  11. procedure proc;
  12.  
  13. implementation
  14. var
  15. app:TCustomApplication;
  16.  
  17. procedure init(p:TCustomApplication);
  18. begin
  19. app := p;
  20. end;
  21.  
  22. procedure proc;
  23. begin
  24. if(app.hasOption('h', 'help')) then // uses CustApp
  25. writeln('yes')
  26. else
  27. writeln('no');
  28. end;
  29.  
  30. initialization
  31. finalization
  32. end.
  33.  
« Last Edit: April 13, 2024, 04:45:25 am by sunjob »

TRon

  • Hero Member
  • *****
  • Posts: 2684
Re: external module connection error
« Reply #3 on: April 13, 2024, 04:46:56 am »
Yes, that probably compiles but is not really advisable because now you have two variables that contain your custom application instance.

You can opt to either pass your application instance to proc (so add a TCustomApplication parameter) or place your application variable inside unit parser instead of in your main project file. Even better would be to use a 3th unit that contains your application variable so that this variable can be shared along all of your units (including your main project file).

edit:  ah I see you edited your code after my initial reply :-) It is better this way but I think I would personally still advise to use a 3th unit.
« Last Edit: April 13, 2024, 04:48:42 am by TRon »

sunjob

  • New Member
  • *
  • Posts: 28
Re: external module connection error
« Reply #4 on: April 13, 2024, 05:01:39 am »
I understand how to do everything in C, everything is simple and clear.
how to do this in Pascal gives me a whirlwind of confusion about the concept of language/structure/interaction.

you can sketch your solution with the third file?

addition:
by “analogy with C” - I added not an object, but a pointer to an object (for a module - the pointer will be an internal variable,
which fits well with the correct concept of data hiding)
imho

TRon

  • Hero Member
  • *****
  • Posts: 2684
Re: external module connection error
« Reply #5 on: April 13, 2024, 05:25:21 am »
I understand how to do everything in C, everything is simple and clear.
Funny that you'd say that because I have the exact same conclusion when working with c in that I find it much more simple and clear using Pascal  :D

Quote
how to do this in Pascal gives me a whirlwind of confusion about the concept of language/structure/interaction.
If you are new to Pascal then this 'feeling' is going to stay there for a while. It does become better, I promise.

Quote
you can sketch your solution with the third file?
Yeah, sure.

Project file:
Code: Pascal  [Select][+][-]
  1. program prj1;
  2.   {$mode objfpc}{$H+}
  3.  
  4. uses
  5.   {$IFDEF UNIX}
  6.   cthreads,
  7.   {$ENDIF}
  8.   Classes, SysUtils, CustApp, { ignore this unit to be a fpc only application --> LazFileUtils} uGlobals, // <-- new 3th unit
  9.   parser;
  10.  
  11. type
  12.   // Types in Pascal are prefixes with a T. That is not a rule but common
  13.   // practice to not confuse variables/constants with types.
  14.   // Everyone I know that programs in Pascal uses this practice so not doing
  15.   // so is able to confuse people.
  16.   // I also asjusted the source-code to use proper indentation, which becomes
  17.   // very important when writing nested loops.
  18.   TMyApplication = class(TCustomApplication)
  19.    protected
  20.     procedure  DoRun; override;
  21.   public
  22.    constructor Create(TheOwner : TComponent); override;
  23.    destructor  Destroy;                       override;
  24.   end;
  25.  
  26. // this is now declared inside unit uGlobals
  27. //var
  28. //  Application : app;
  29.  
  30. procedure TMyApplication.DoRun;
  31. begin
  32.   // ignore this line --> parser.init(Application);
  33.   parser.proc;
  34.   Terminate;
  35. end;
  36.  
  37. constructor TMyApplication.Create(TheOwner : TComponent);
  38. begin
  39.   inherited Create(TheOwner);
  40.   StopOnException := True;
  41. end;
  42.  
  43. destructor TMyApplication.Destroy;
  44. begin
  45.   inherited Destroy;
  46. end;
  47.  
  48. // Do not declare this variable in your project file anymore but instead use
  49. // a 3th unit which I named uGlobals
  50. // var Application : app;
  51. {$R *.res}
  52. begin
  53.   Application       := TMyApplication.Create(nil);
  54.   Application.Title := 'app';
  55.   Application.Run;
  56.   Application.Free;
  57. end.
  58.  

parser file:
Code: Pascal  [Select][+][-]
  1. unit parser;
  2.  
  3. {$mode objfpc}{$H+}  // place this here and not inside the interface section
  4.  
  5. interface
  6.  
  7. uses
  8.   {$IFDEF UNIX}
  9.   cthreads,
  10.   {$ENDIF}
  11.   Classes, SysUtils, CustApp;
  12.  
  13.  
  14. // not necessary anymore --> procedure init(p:TCustomApplication);
  15. procedure proc;
  16.  
  17. implementation
  18.  
  19. uses
  20.   uGlobals;  // <-- add 3th unit that contains global variables which can be used by all of your units in order to access global variables.
  21.  
  22. // Note necessary anymore, use application from uGLobals
  23. // var
  24. // app:TCustomApplication;
  25.  
  26. //procedure init(p:TCustomApplication);
  27. //begin
  28. //app := p;
  29. //end;
  30.  
  31. procedure proc;
  32. begin
  33.   if(appplication.hasOption('h', 'help')) then // uses CustApp
  34.     writeln('yes')
  35.   else
  36.     writeln('no');
  37. end;
  38.  
  39. initialization
  40.  
  41. finalization
  42.  
  43. end.
  44.  

3th unit, that I named uGlobals
Code: Pascal  [Select][+][-]
  1. unit uGlobals;
  2.  
  3. interface
  4.  
  5. uses
  6.   CustApp;
  7.  
  8. var
  9.   Application: TCustomApplication;
  10.  
  11. implementation
  12.  
  13. end.
  14.  

Is that more clear ?

It is a common practice that is used to 'share' common declarations between several different units on your project. This becomes more evident when using Lazarus and have many visual forms.

Quote
addition:
by “analogy with C” - I added not an object, but a pointer to an object (for a module - the pointer will be an internal variable,
which fits well with the correct concept of data hiding)
imho
Yes, but you basically do the same by passing TCustomApplication to your init routine (in practice that is a pointer).

edit: I pasted the wrong parser unit, corrected.
« Last Edit: April 13, 2024, 05:38:07 am by TRon »

sunjob

  • New Member
  • *
  • Posts: 28
Re: external module connection error
« Reply #6 on: April 13, 2024, 05:51:25 am »
after all, Pascal is an incredibly confusing language
- change/edit of the main & module
- adding a 3rd file

in C
- no need to edit anything
- no need to add a 3rd file
done in one line
Code: C  [Select][+][-]
  1. extern TCustomApplication* app
  2.  

C/C++ - rules  O:-)

thank you very much!!!
« Last Edit: April 13, 2024, 05:55:32 am by sunjob »

Joanna

  • Hero Member
  • *****
  • Posts: 811
Re: external module connection error
« Reply #7 on: April 13, 2024, 04:24:07 pm »
Quote
after all, Pascal is an incredibly confusing language
Another good example of why people should learn pascal before being allowed to post here
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

sunjob

  • New Member
  • *
  • Posts: 28
Re: external module connection error
« Reply #8 on: April 13, 2024, 07:25:19 pm »
...

> sorry to see you go so soon
I’m here, I haven’t gone anywhere!

> Your statements are inaccurate to say the less.
more definitely accurate!

in my statement I gave an example of how "in this case" С/С++ is simply magnificent and concise.

I hope that here on the forum, we have the right to express our point of view ON THE TOPIC?

thank

p.s.
I will not support/to continue the dialogue "c/c++ vs fpc"

« Last Edit: April 14, 2024, 02:16:21 am by sunjob »

alpine

  • Hero Member
  • *****
  • Posts: 1111
Re: external module connection error
« Reply #9 on: April 14, 2024, 09:00:16 pm »
after all, Pascal is an incredibly confusing language
- change/edit of the main & module
- adding a 3rd file

in C
- no need to edit anything
- no need to add a 3rd file
done in one line
Code: C  [Select][+][-]
  1. extern TCustomApplication* app
  2.  
Not quite. You must include a header file with the TCustomApplication definition. Most probably you'll have one *.h file (prj1.h) and two *.cpp files (prj1.cpp+parser.cpp).

FPC unlike C/C++ has it's own modularization system (with unit files) and doesn't rely on linker to resolve externals. Thus way it can compile/build much faster and to put more restrictions when accessing public symbols. In C/C++ you can reach sneakily anything you want with the extern.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11534
  • FPC developer.
Re: external module connection error
« Reply #10 on: April 14, 2024, 09:12:57 pm »
FPC unlike C/C++ has it's own modularization system

Incorrect. 40 years after Wirth languages got a module system, C++ also added it in C++20:

alpine

  • Hero Member
  • *****
  • Posts: 1111
Re: external module connection error
« Reply #11 on: April 14, 2024, 09:27:47 pm »
FPC unlike C/C++ has it's own modularization system

Incorrect. 40 years after Wirth languages got a module system, C++ also added it in C++20:
I'm behind too.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

sunjob

  • New Member
  • *
  • Posts: 28
Re: external module connection error
« Reply #12 on: April 15, 2024, 04:58:09 am »
Thank you very much everyone for your help!
... Forever Young ...  ::)

Joanna

  • Hero Member
  • *****
  • Posts: 811
Re: external module connection error
« Reply #13 on: April 15, 2024, 03:49:11 pm »
Thanks for disparaging my favorite programming language  >:D
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

 

TinyPortal © 2005-2018