Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2012-03

Strange dependency of units

74 messages · 19 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Jürgen Hestermann

I have my own general purpose unit with functions and procedures I often use. There are also some routines that operate on TStringGrid types so I had to add GRIDS to the uses clause in the interface part of this unit. If I now write a very simple "Hello World" program that uses just one simple function from my unit I get errors

Error: Undefined symbol: WSRegisterCustomImageList Error: Undefined symbol: WSRegisterMenuItem
etc.

at the end of my program. After a long searching I found out that I had to add INTERFACES to the uses clause of my program. My questions:

How should anybody know that this is required in this situation? Why is the INTERFACES unit not required in the unit itself?

Reply by email

Mattias Gaertner
to Jürgen Hestermann
Show quoted text 15 lines
I have my own general purpose unit with functions and procedures I often use. There are also some routines that operate on TStringGrid types so I had to add GRIDS to the uses clause in the interface part of this unit. If I now write a very simple "Hello World" program that uses just one simple function from my unit I get errors Error: Undefined symbol: WSRegisterCustomImageList Error: Undefined symbol: WSRegisterMenuItem etc. at the end of my program. After a long searching I found out that I had to add INTERFACES to the uses clause of my program. My questions: How should anybody know that this is required in this situation? Why is the INTERFACES unit not required in the unit itself?

Grids is is part of the platform independent LCLBase. The unit 'interfaces' (i.e. package LCL) provides the implementation.
It is similar to a class like TStrings with abstract methods and the a full class like TStringList.
The compiler can tell that "TStrings.Create" is a bad idea, but it can not tell what full class to use instead.
It's the same with Grids. The compiler can tell that the implementation is missing, but you have to choose the implementation.

The IDE has some automatic checks for LCL applications. Maybe some can be extended.

Hint: When you use Cody to add the grids unit to the uses section, it will automatically add the LCL as dependency.

Mattias

Reply by email

Jürgen Hestermann
to Mattias Gaertner
Show quoted text 6 lines
> How should anybody know that this is required in this situation? > Why is the INTERFACES unit not required in the unit itself? Grids is part of the platform independent LCLBase. The unit 'interfaces' (i.e. package LCL) provides the implementation.

How should I know this?

And why do I *not* need the INTERFACES unit in my general purpose unit? There I only 'use' GRIDS.

Show quoted text 6 lines
It is similar to a class like TStrings with abstract methods and a full class like TStringList. The compiler can tell that "TStrings.Create" is a bad idea, but it can not tell what full class to use instead. It's the same with Grids. The compiler can tell that the implementation is missing, but you have to choose the implementation.

Well, I don't know anything about packages. I come from Turbo/Virtual Pascal. I always struggle with this very strange concept of packages. It seems that it generates more problems than it saves. I only want to use libraries (units). It was just a great step forward with Turbo Pascal to introduce the concept of units. No need to think about dependencies anymore. If you use a unit that again uses other units the compiler/IDE took care about these things and the only need was to configure where to search for them (which was already done for libraries that came with the IDE). In case it missed the source of a unit it clearly told me *which* unit it could not compile. But now I have to fight with these internals myself. I have to learn all about used packages (which units do they include? which dependencies exist? etc.) even when I'm writing a simple 'Hello World' program that uses a simple unit. Strange.

Hint: When you use Cody to add the grids unit to the uses section, it will automatically add the LCL as dependency.

What is Cody? As said: I added the 'uses grids' clause to my unit only. I don't need it in my simple console program. I also never added the grids unit to my other programs. The compiler should know what it has to compile (and link) because it was declared in the unit. If I create a graphic program with Larazus' 'new project' function the INTERFACES unit is added automatically to the program (but no GRIDS!). But if I create a new console program and then use my unit (because I need some non-grid functions) I get errors but don't know what they are all about.

Reply by email

Jürgen Hestermann
to Reinier Olislagers
Show quoted text 9 lines
On 31-3-2012 15:08, J?rgen Hestermann wrote: >> Hint: When you use Cody to add the grids unit to the uses section, it >> will automatically add the LCL as dependency. >> > What is Cody? > http://wiki.lazarus.freepascal.org/index.php?title=Special%3ASearch&search=cody&fulltext=Search

This reminds me on this: http://www.ztw3.com/forum/forum_entry.php?id=114358 You answer sounds like the Linux part ;-)
Is Lazarus on the same way?

Reply by email

Reinier Olislagers
to Jürgen Hestermann
J?rgen Hestermann wrote 12 lines
Reinier Olislagers schrieb: > On 31-3-2012 15:08, J?rgen Hestermann wrote: > >>> Hint: When you use Cody to add the grids unit to the uses section, it >>> will automatically add the LCL as dependency. >>> >> What is Cody? > http://wiki.lazarus.freepascal.org/index.php?title=Special%3ASearch&search=cody&fulltext=Search This reminds me on this: http://www.ztw3.com/forum/forum_entry.php?id=114358 You answer sounds like the Linux part ;-) Is Lazarus on the same way?

No idea.
Just wanted to encourage you that there often is documentation about concepts... even though it may not always be complete or correct.

Regards,
Reinier

BTW: Haven't learned Java, so I suspect that's actually good ;)

Reply by email

David W Noon
to Jürgen Hestermann: This reminds me on this: http://www.ztw3.com/forum/forum_entry.php?id=114358 You answer…

On Sat, 31 Mar 2012 15:22:05 +0200, J?rgen Hestermann wrote about Re: [Lazarus] Strange dependency of units:

http://www.ztw3.com/forum/forum_entry.php?id=114358 You answer sounds like the Linux part ;-) Is Lazarus on the same way?

Hey! I run Gentoo Linux, so there is no step 2 on my machines. I am permanently in step 1. ... :-))

Regards, Dave [RLU #314465] ======================================================================= (David W Noon) =======================================================================

Reply by email

Mattias Gaertner
to Jürgen Hestermann: This reminds me on this: http://www.ztw3.com/forum/forum_entry.php?id=114358 You answer…
Show quoted text 13 lines
Reinier Olislagers schrieb: > On 31-3-2012 15:08, J?rgen Hestermann wrote: > >>> Hint: When you use Cody to add the grids unit to the uses section, it >>> will automatically add the LCL as dependency. >>> >> What is Cody? >> > http://wiki.lazarus.freepascal.org/index.php?title=Special%3ASearch&search=cody&fulltext=Search > This reminds me on this: http://www.ztw3.com/forum/forum_entry.php?id=114358 You answer sounds like the Linux part ;-) Is Lazarus on the same way?

In the past the programs that used only parts of the LCL compiled, but would then later fail at runtime at some strange place. Now you already see at compile time that something is missing. That's definitely better.

And the IDE has already some checks for common mistakes.

Mattias

Reply by email

Jürgen Hestermann
to Mattias Gaertner: On Sat, 31 Mar 2012 15:22:05 +0200 In the past the programs that used only parts of the…
In the past the programs that used only parts of the LCL compiled, but would then later fail at runtime at some strange place. Now you already see at compile time that something is missing. That's definitely better.

Of course, you are right: It could be even worse.

And the IDE has already some checks for common mistakes.

Mistake? Using a self-written unit is a mistake? Not knowing that GRIDS requires INTERFACES is a mistake?
Shouldn't GRIDS have a uses clause for INTERFACES? If yes, why is it not included?
If no, why is this so?

Reply by email

Reinier Olislagers
to Jürgen Hestermann: Of course, if I *wanted* to get information about "Cody" I know that I could use Google.…
J?rgen Hestermann wrote 7 lines
Reinier Olislagers schrieb: > Just wanted to encourage you that there often is documentation about > concepts... even though it may not always be complete or correct. Of course, if I *wanted* to get information about "Cody" I know that I could use Google. The question was: Do I *need* to know about it to program with Lazarus?

vs
On 31-3-2012 15:08, J?rgen Hestermann wrote:
"What is Cody?"

????

Reply by email

Jürgen Hestermann
to Reinier Olislagers
Show quoted text 7 lines
> Of course, if I *wanted* to get information about "Cody" I know that I > could use Google. > The question was: Do I *need* to know about it to program with Lazarus? vs On 31-3-2012 15:08, J?rgen Hestermann wrote: "What is Cody?" ????

Well, my question was a reaction to Mattias' "hint":

"When you use Cody to add the grids unit to the uses section, it will automatically add the LCL as dependency."

I found this a bit astonishing because why should I use anything else than my keyboard to add a unit to my program? And because I never heard about "Cody" before I wrote "What is Cody?". It was just yet another answer in the sense that it does not answer your question but instead hints you to yet another topic so that you get into the Linux-problem-solve mechnism to waste your live on another topic that leads you to another topic that leads you to another topic.. over and over again. You only never get back to solve your original problem, you may even forget about it. The reason for the success of Turbo Pascal was just that you did *not* have to have all the knowledge about what happens in the background. I painfully miss this idea in Lazarus.

Reply by email

Mattias Gaertner
to Jürgen Hestermann: Of course, you are right: It could be even worse. Mistake? Using a self-written unit is a…
Show quoted text 6 lines
Mattias Gaertner schrieb: [...] > And the IDE has already some checks for common mistakes. Mistake? Using a self-written unit is a mistake? Not knowing that GRIDS requires INTERFACES is a mistake?

?
You asked on which way Lazarus is and I gave examples where things are getting easier. Of course there is always room for more helpers.

You made the mistake to use grids without an implementation (e.g. LCL interfaces).

Shouldn't GRIDS have a uses clause for INTERFACES? If yes, why is it not included? If no, why is this so?

I already tried to explain that. I'm not sure what you did not understand about the concept of "abstract method". Maybe this helps: The LCL "interfaces" is just one possible implementation. Theoretically you can implement another one. At the moment the LCL unit "interfaces" is the only supported one.
Theoretically it might be possible to use interfaces in grids, but that would make many other things more complicated.

Mattias

Reply by email

Mattias Gaertner
to Jürgen Hestermann: Well, my question was a reaction to Mattias' "hint": "When you use Cody to add the grids…
Show quoted text 16 lines
Reinier Olislagers schrieb: >> Of course, if I *wanted* to get information about "Cody" I know that I >> could use Google. >> The question was: Do I *need* to know about it to program with Lazarus? > vs > On 31-3-2012 15:08, J?rgen Hestermann wrote: > "What is Cody?" > ???? Well, my question was a reaction to Mattias' "hint": "When you use Cody to add the grids unit to the uses section, it will automatically add the LCL as dependency." I found this a bit astonishing because why should I use anything else than my keyboard to add a unit to my program?

You can use the Cody dictionary with your keyboard only.

Show quoted text 10 lines
And because I never heard about "Cody" before I wrote "What is Cody?". It was just yet another answer in the sense that it does not answer your question but instead hints you to yet another topic so that you get into the Linux-problem-solve mechnism to waste your live on another topic that leads you to another topic that leads you to another topic.. over and over again. You only never get back to solve your original problem, you may even forget about it. The reason for the success of Turbo Pascal was just that you did *not* have to have all the knowledge about what happens in the background. I painfully miss this idea in Lazarus.

I'm sorry for trying to help you and I'm glad that Lazarus users are so spoiled.
The hint was a about a tool that reduces the burden of knowing to which package a unit belongs, search paths and dependencies. If you have trouble with "hints" then just ignore them.

Mattias

Reply by email

Mattias Gaertner
to Jürgen Hestermann: I have my own general purpose unit with functions and procedures I often use. There are…
Show quoted text 8 lines
I have my own general purpose unit with functions and procedures I often use. There are also some routines that operate on TStringGrid types so I had to add GRIDS to the uses clause in the interface part of this unit. If I now write a very simple "Hello World" program that uses just one simple function from my unit I get errors Error: Undefined symbol: WSRegisterCustomImageList Error: Undefined symbol: WSRegisterMenuItem

I added a FAQ, improved the jump in the messages window and added a comment in the sources.

Mattias

Reply by email

Jürgen Hestermann
to Mattias Gaertner: On Sat, 31 Mar 2012 17:04:16 +0200 You can use the Cody dictionary with your keyboard…
The hint was about a tool that reduces the burden of knowing to which package a unit belongs, search paths and dependencies.

Why is this at all necessary? I don't get it of what use such a complicated and error prone construct like packages should serve for if it is not rock solid. Is this an improvement over simple to use units? In units, all dependencies are automatically(!) resolved by the software. Why is this impossible for packages? I was not even aware that I used a package. I just used a unit (grids).

Reply by email

Jürgen Hestermann
to Mattias Gaertner: On Sat, 31 Mar 2012 16:42:53 +0200 ? You asked on which way Lazarus is and I gave…
You made the mistake to use grids without an implementation (e.g. LCL

interfaces).

Implementation? What's this again? It's no longer enough to use a unit? Sorry, but it seems that there is a very steep learning curve even for former (Turbo..) Pascal programmers.
I have to learn a lot just to be able to program with Lazarus. It seems to be for long term nerds only.
It has become nearly as complicated as C and relatives.

I'm not sure what you did not understand about the concept of

"abstract method".

Everything. If it leads to such results this concept seems to be not very good.

The LCL "interfaces" is just one possible implementation. Theoretically you can implement another one. At the moment the LCL unit "interfaces" is the only supported one.

Shouldn't these dependencies somehow be handled by the compiler/linker? Why is the programmer bothered with it? There could be a default "implementation" that would be used in these cases. Now the programmer has to investigate in the concept *and* how Lazarus/FPC handles it. Not very convenient.

Reply by email

Mattias Gaertner
to Jürgen Hestermann: Why is this at all necessary? I don't get it of what use such a complicated and error…
Show quoted text 10 lines
Mattias Gaertner schrieb: > The hint was about a tool that reduces the burden of knowing to > which package a unit belongs, search paths and dependencies. Why is this at all necessary? I don't get it of what use such a complicated and error prone construct like packages should serve for if it is not rock solid. Is this an improvement over simple to use units? In units, all dependencies are automatically(!) resolved by the software. Why is this impossible for packages? I was not even aware that I used a package. I just used a unit (grids).

In Lazarus packages are groups of units. This is not only useful for big projects, it makes sharing code easier in general. Each package has its own compiler options. For example the LCL units need some flags like inlining and C style operators and some linker options. When you copy a package to another machine you don't have to adapt any search paths or compiler options.
When some compiler option changes or a sub directory is renamed or the package is moved to another location on you disk, you don't have to adapt all your projects that uses the package.
Packages allow to share ppu files. You don't have to recompile the LCL for every project. Each package has its own directory where its ppu files are stored.

And packages can do more than compiling. For example documentation and translation.

Mattias

Reply by email

Mattias Gaertner
to Jürgen Hestermann: interfaces). Implementation? What's this again? It's no longer enough to use a unit?…
Show quoted text 7 lines
Mattias Gaertner schrieb: > You made the mistake to use grids without an implementation (e.g. LCL interfaces). Implementation? What's this again? It's no longer enough to use a unit? Sorry, but it seems that there is a very steep learning curve even for former (Turbo..) Pascal programmers.

AFAIR Turbo Pascal was pretty simple. I really liked it. It supported only one target platform and the OOP came with Delphi.
Compare the compiler flags of TP and FPC. TP is a toy compared to FPC.

Show quoted text 10 lines
I have to learn a lot just to be able to program with Lazarus. It seems to be for long term nerds only. It has become nearly as complicated as C and relatives. > I'm not sure what you did not understand about the concept of "abstract method". Everything. If it leads to such results this concept seems to be not very good.

"Such results"?

The normal user creates a LCL application and everything is setup for him.

You didn't use the tools, but instead set up your project manually. And now you expect that the compiler/IDE magically scans your brain to find out what your intention was and complete what you have started?

This is like installing Gentoo Linux and then whining about Linux is so complicated and only for nerds.

Show quoted text 5 lines
> The LCL "interfaces" is just one possible implementation. Theoretically > you can implement another one. At the moment the LCL unit "interfaces" > is the only supported one. Shouldn't these dependencies somehow be handled by the compiler/linker?

They are handled automatically if you let the IDE help you.

Why is the programmer bothered with it?

Because you choose to. I bet most Lazarus users have never seen this linker error.

There could be a default "implementation" that would be used in these cases. Now the programmer has to investigate in the concept *and* how Lazarus/FPC handles it. Not very convenient.

Mattias

Reply by email

Žilvinas Ledas
to Jürgen Hestermann: interfaces). Implementation? What's this again? It's no longer enough to use a unit?…

Hello,

J?rgen Hestermann wrote 17 lines
Mattias Gaertner schrieb: > You made the mistake to use grids without an implementation (e.g. LCL interfaces). Implementation? What's this again? It's no longer enough to use a unit? Sorry, but it seems that there is a very steep learning curve even for former (Turbo..) Pascal programmers. I have to learn a lot just to be able to program with Lazarus. It seems to be for long term nerds only. It has become nearly as complicated as C and relatives. > I'm not sure what you did not understand about the concept of "abstract method". Everything. If it leads to such results this concept seems to be not very good.

My observation from the conversation till now: I believe you should learn a bit about Object-oriented programming and its concepts (abstract methods being one ot them).
This should let you use Object Pascal language much more easily.

Best regards,
?ilvinas Ledas

Reply by email

Jürgen Hestermann
to Mattias Gaertner: On Sat, 31 Mar 2012 19:41:02 +0200 In Lazarus packages are groups of units. This is not…
Each package has its own compiler options. For example the LCL units need some flags like inlining and C style operators and some linker options.

Why isn't this simply added to the source files (compiler switches)? It would be much easier, rock solid and would even allow different settings for each unit. No need for a complicated construct like packages.

When you copy a package to another machine you don't have to adapt any search paths or compiler options.

Realy? I think I have to somehow tell Lazarus about a new package, don't I? So what is the advantage to clicking on "Load package" or whatever and specifying the location path of the package over copying the units into the directory where Lazarus expect them?

When some compiler option changes or a sub directory is renamed or the package is moved to another location on you disk, you don't have to adapt all your projects that uses the package.

I don't see this. When I rename a directory which Lazarus uses then I think it will fail. So in the end I need to tell Lararus about the change anyway. I have to find out how and where to do this. What is the difference to knowing where to specify search paths and change them?

Packages allow to share ppu files. You don't have to recompile the LCL for every project. Each package has its own directory where its ppu files are stored.

That's the concept of units. I just wonder why this is/was not enough.

Reply by email

Jürgen Hestermann
to Mattias Gaertner: On Sat, 31 Mar 2012 19:41:05 +0200 AFAIR Turbo Pascal was pretty simple. I really liked…
AFAIR Turbo Pascal was pretty simple. I really liked it. It supported only one target platform and the OOP came with Delphi.

OOP was already implemented in Borland Pascal.

Compare the compiler flags of TP and FPC. TP is a toy compared to FPC.

But what has all this to do with the concept of packages? The concepts used in TP where enough to allow arbitrary complex applications. And my main critic about all this is, that even when new concepts are introduced they should be rock solid. This looks more like a design study.

The normal user creates a LCL application and everything is setup for

him.

That's exactly what I did. I used Larazus to create a console application. I then added my general purpose unit to the uses clause. Then compile failed with an error message that had nothing to do with my program or unit.

You didn't use the tools, but instead set up your project manually.

Not true.

And now you expect that the compiler/IDE magically scans your brain to find out what your intention was and complete what you have started?

No. But you expect me to scan the brain of the programmers of the LCL to find out why I get this error message.

> Shouldn't these dependencies somehow be handled by the compiler/linker? They are handled automatically if you let the IDE help you.

It seems they are not.

> Why is the programmer bothered with it? Because you choose to.

I did not.

I bet most Lazarus users have never seen this linker error.

I don't know. But still what I did was a standard thing:

*) Write a unit
*) Create a program (via Lararus) that uses the unit (which I use in nearly all programs)

What is wrong with this?

To sum it up:
If I use a unit GRIDS in a unit and a program uses this unit how should I know that this program has to use the unit INTERFACES? Why is this unit not required in my unit but in my program? That's completely rediculous. Why does the existing rock solid unit concept no longer work? It seems some other concept has broken it.

Reply by email

Mattias Gaertner
to Jürgen Hestermann: Why isn't this simply added to the source files (compiler switches)? It would be much…
Show quoted text 7 lines
Mattias Gaertner schrieb: > Each package has its own compiler options. For example the LCL units need > some flags like inlining and C style operators and some linker options. Why isn't this simply added to the source files (compiler switches)? It would be much easier, rock solid and would even allow different settings for each unit. No need for a complicated construct like packages.

Individual settings for hundreds of units?
No one can remember that.
It would mean every developer has to read the header of a unit every time he wants to read/extend it.

Show quoted text 5 lines
> When you copy a package to another machine you don't have to adapt any > search paths or compiler options. Realy? I think I have to somehow tell Lazarus about a new package, don't I?

Yes.
Or an installer can add a lpl file.

So what is the advantage to clicking on "Load package" or whatever and specifying the location path of the package over copying the units into the directory where Lazarus expect them?

You are free to put the package anywhere you like. You can easily switch between different versions.

Show quoted text 8 lines
> When some compiler option changes or a sub directory is renamed or the > package is moved to another location on you disk, you don't have to > adapt all your projects that uses the package. I don't see this. When I rename a directory which Lazarus uses then I think it will fail. So in the end I need to tell Lararus about the change anyway. I have to find out how and where to do this. What is the difference to knowing where to specify search paths and change them?

When you rename a directory you have to adapt only one place. Over the last years many directories and compiler options have changed in the Lazarus sources and the biggest part of those changes had no effect on the users' projects.
I other words: packages gives developers more freedom to refactor their code.

Show quoted text 5 lines
> Packages allow to share ppu files. You don't have to recompile > the LCL for every project. Each package has its own directory where its > ppu files are stored. That's the concept of units. I just wonder why this is/was not enough.

The concept/advantage of units is to share code.
The concept/advantage of ppu is to compile less.
The ppus do not store where they came from or how they were compiled. This means for example when you change a flag the compiler can not tell what ppu needs recompiling. You have to rebuild everything manually.
With packages you know what ppu belongs to which unit and how they were compiled. The IDE will automatically recompile packages clean if you change flags.

Mattias

Reply by email

Mattias Gaertner
to Jürgen Hestermann: OOP was already implemented in Borland Pascal. But what has all this to do with the…
Show quoted text 5 lines
Mattias Gaertner schrieb: > AFAIR Turbo Pascal was pretty simple. I really liked it. > It supported only one target platform and the OOP came with Delphi. OOP was already implemented in Borland Pascal.

AFAIK this was only the "object" syntax, not the "class" syntax. IMO the "object" syntax is too limited to be called true OOP. Some people say that javascript is OO, so I guess you can say TP had OOP.

> Compare the compiler flags of TP and FPC. TP is a toy compared to FPC. But what has all this to do with the concept of packages? The concepts used in TP where enough to allow arbitrary complex applications.

The concepts of assembler allow that too.

And my main critic about all this is, that even when new concepts are introduced they should be rock solid. This looks more like a design study.

The concept is pretty simple and works nice since 10 years.

Show quoted text 7 lines
> The normal user creates a LCL application and everything is setup for him. That's exactly what I did. I used Larazus to create a console application. I then added my general purpose unit to the uses clause. Then compile failed with an error message that had nothing to do with my program or unit.

A console application is for simple stdin/stdout programs that runs in the DOS box, the OS X terminal, the Linux shell, etc.

You did not create a LCL application. When you create a new project, there is a "Description".

Show quoted text 8 lines
[...] I don't know. But still what I did was a standard thing: *) Write a unit *) Create a program (via Lararus) that uses the unit (which I use in nearly all programs) What is wrong with this?

Nothing. The unit just can not work on its own. You just have to add an implementation.

To sum it up: If I use a unit GRIDS in a unit and a program uses this unit how should I know that this program has to use the unit INTERFACES?

As I wrote two times: It does not need interfaces. Here is an example that compiles without interfaces:

program project1;
{$mode objfpc}{$H+}
uses
  Classes, Grids, NoGUIWSFactory;
begin
  writeln('Works');
end.
Why is this unit not required in my unit but in my program? That's completely rediculous. Why does the existing rock solid unit concept no longer work? It seems some other concept has broken it.

Please distinguish between "Compiles" and "Works".

It is not enough to use unit "interfaces", a normal LCL application also requires an Application.Initialize call.

The unit concept is powerful, but it is not almighty.

Mattias

Reply by email

Jürgen Hestermann
to Mattias Gaertner
> That's exactly what I did. I used Larazus to create a console > application. I then added my general purpose unit to the uses clause. > Then compile failed with an error message that had nothing to do

with my

> program or unit. A console application is for simple stdin/stdout programs that runs in the DOS box, the OS X terminal, the Linux shell, etc.

Exactly. That's what I wanted to create. I only included my general purpose unit which I also use for LCL programs. Some functions exist in this unit that operate on TStringGrid type (but I did not use them in my console program) so I had to add GRIDS to the uses clause of this unit. The astonishing thing now is, that my (console) program only compiles when I add the interfaces unit to the program although I never actively used it.

Show quoted text 8 lines
> *) Write a unit > *) Create a program (via Lararus) that uses the unit (which I use in > nearly all programs) > > What is wrong with this? Nothing. The unit just can not work on its own. You just have to add an implementation.

??
On its own? I used it in my (console) program.
Add an implementation? My program is a simple text mode console program. Why should I have 'added' something to it?

Show quoted text 10 lines
As I wrote two times: It does not need interfaces. Here is an example that compiles without interfaces: program project1; {$mode objfpc}{$H+} uses Classes, Grids, NoGUIWSFactory; begin writeln('Works'); end.

When I create a new console application, delete everything in it and add your program from above I get:
"Can't find unit Grids used by project1."
Why can't it find this unit? Lazarus was installed with it. So it should know where it has put it.

It is not enough to use unit "interfaces", a normal LCL application also requires an Application.Initialize call.

I did *not* want to create an LCL application! It was a simple console program.

Reply by email

Marco van de Voort
to Mattias Gaertner: On Sun, 01 Apr 2012 11:20:49 +0200 AFAIK this was only the "object" syntax, not the…
Mattias Gaertner wrote
> OOP was already implemented in Borland Pascal. AFAIK this was only the "object" syntax, not the "class" syntax. IMO the "object" syntax is too limited to be called true OOP.

TP Object syntax was perfectly valid oop. It provided mechanisms for all important OOP features:

1. combining data and behaviour (code)
2. instantiation - one could instantiate multiple objects
3. encapsulation - private, public
4. polymorphism - provided by inhertiance + virtual methods.

Reply by email

Martin
to Jürgen Hestermann: with my Exactly. That's what I wanted to create. I only included my general purpose unit…
J?rgen Hestermann wrote 17 lines
Mattias Gaertner schrieb: >> That's exactly what I did. I used Larazus to create a console >> application. I then added my general purpose unit to the uses clause. >> Then compile failed with an error message that had nothing to do with my >> program or unit. > > A console application is for simple stdin/stdout programs that runs in > the DOS box, the OS X terminal, the Linux shell, etc. Exactly. That's what I wanted to create. I only included my general purpose unit which I also use for LCL programs. Some functions exist in this unit that operate on TStringGrid type (but I did not use them in my console program) so I had to add GRIDS to the uses clause of this unit. The astonishing thing now is, that my (console) program only compiles when I add the interfaces unit to the program although I never actively used it.

I think, this means looking at 2 issues.

1) using grids, but without any platform/GUI dependency
2) why the need to add interfaces by hand

1)
the unit grids contains stuff, that is platform/GUI dependent.

Actually the basic concept of a unit is use it all or nothing. So by using Grids, you should expect all the platform/GUI dependent stuff to end up in your application.
(which means a need for interfaces => leading to issue 2, why isn't it included/used by grids)

Sure you only refer (and only want to use) some parts of Grids, which would not require that. And you use smart linking, and smart linking usually works well.
But smart linking is an addition, an extra on top of the concept of units (the all unit or nothing concept).

And there are cases where smart-linking does not work. And you encountered one. Some of the methods, of some classes in Grids can not be smart linked (IIRC virtual/overridden class methods, maybe all virtual/overridden).
So they end up in your console app.

In other words: Using the unit Grids, even with smart linking, makes your app platform/GUI dependent. (even though this parts of the code will not be called)
For this cases the "NoGui" widgetset exists. It provides (or should provide) empty methods for this.

2)
The design decision not to use interfaces in Grid was done long ago. (Thinks were different then, one think led to another...)

In theory that could be changed (like a lot of thinks *could* be done). In practise this may never happen (if only due to time available...). A re-design that big could have a lot of other side effects (which probably could all be remedied). But the cost might just be to high. (Yet I guess, if someone wants to step forward....) I haven't looked into details, so I can't say more about it.

Originally a default implementation (a class wit abstract methods) did exist, so using grids, without interfaces would compile.
- If the code was not called: good
- If by some chance it was called (even totally unexpected): crash

The problem: this old implementation was very bad to smart linking. It caused a real lot of other unused stuff go into every exe. In order to make it more smart-linkable (refers to a location different from answer "1") the abstract method declarations had to be dropped.
- Benefit: *IF* it compiles, it wont crash by calling an abstract method
- Disadvantage: In some (IMHO rare (yet still valid)) cases: you have to know, that you have to add interfaces.

Reply by email

Hans-Peter Diettrich
to Jürgen Hestermann: OOP was already implemented in Borland Pascal. But what has all this to do with the…
Show quoted text 6 lines
> Compare the compiler flags of TP and FPC. TP is a toy compared to FPC. But what has all this to do with the concept of packages? The concepts used in TP where enough to allow arbitrary complex applications. And my main critic about all this is, that even when new concepts are introduced they should be rock solid. This looks more like a design study.

Many languages have problems with e.g. multi-platform issues or, in case of Lazarus, with multiple implementations (of the widgetset), selectable at build time. The same for (third-party) libraries, which may or may not come with source code. That's why features like "packages" have been invented, to overcome such management problems (search paths...). Of course everybody can manage that himself, writing and updating Makefiles etc., but then he has no assistance by other tools (expect written by himself).

Show quoted text 7 lines
> The normal user creates a LCL application and everything is setup for him. That's exactly what I did. I used Larazus to create a console application. I then added my general purpose unit to the uses clause. Then compile failed with an error message that had nothing to do with my program or unit.

IIRC your case is somewhat non-standard, because you use an *abstract* class. In such an case *every* user has to indicate the unit or package, where that abstract interface is implemented.

You are right in so far as Lazarus contains a couple of such abstract classes, some of which *never* can be implemented outside their declaring unit. Perhaps the developers *wanted* to allow for more flexibility, by declaring abstract classes and virtual methods first, but in many cases they forgot to make their supplied default implementation used *by default* (e.g. GRIDS), or they forgot to add features that allow to create alternative implementations at all (e.g. TDragManager).

More discussion of such issues should lead to an improved situation, where the inventors have fixed obvious flaws, and have added documentation and means for alternative implementations.

DoDi

Reply by email

Hans-Peter Diettrich
to Mattias Gaertner: On Sun, 01 Apr 2012 11:20:49 +0200 AFAIK this was only the "object" syntax, not the…
Show quoted text 11 lines
On Sun, 01 Apr 2012 11:20:49 +0200 J?rgen Hestermann wrote: > Mattias Gaertner schrieb: > > AFAIR Turbo Pascal was pretty simple. I really liked it. > > It supported only one target platform and the OOP came with Delphi. > > OOP was already implemented in Borland Pascal. AFAIK this was only the "object" syntax, not the "class" syntax. IMO the "object" syntax is too limited to be called true OOP.

Little differences exist between the "Object" and "Class" types, and most projects can be made work with both, not needing such adds. IMO most additions are not related to OO at all (like RTTI), or bypass acknowledged OOP restrictions.

DoDi

Reply by email

Hans-Peter Diettrich
to Jürgen Hestermann: with my Exactly. That's what I wanted to create. I only included my general purpose unit…
Show quoted text 12 lines
Mattias Gaertner schrieb: >> That's exactly what I did. I used Larazus to create a console >> application. I then added my general purpose unit to the uses clause. >> Then compile failed with an error message that had nothing to do with my >> program or unit. > > A console application is for simple stdin/stdout programs that runs in > the DOS box, the OS X terminal, the Linux shell, etc. Exactly. That's what I wanted to create. I only included my general purpose unit which I also use for LCL programs.

The design of your "general purpose" unit obviously is flawed. Console and GUI applications differ in many subtle ways, and I suggest that you use {$IFnDEF CONSOLE} to exclude everything that is available and usable only in a GUI application. This general purpose solution already exists, you simply did not yet find out how to use it :-)

There exist more hidden pitfalls, e.g. that you have to use SysUtils in order to make SEH work - a Delphi heritage.

DoDi

Reply by email

Sven Barth
to Hans-Peter Diettrich
"Hans-Peter Diettrich" wrote
There exist more hidden pitfalls, e.g. that you have to use SysUtils in

order to make SEH work - a Delphi heritage.

This is wrong in multiple ways:
* SEH itself is not fully utilized by FPC (though that recently changed on Win64), it only sets the UnexpectedExceptionHandler to integrate its own platform independant exception handling mechanism
* Exception handling is implemented in the System unit. SysUtils merely defines the Exception class and registers a conversion function for runtime errors to descendants of this class. It's perfectly valid to use exceptions that derive directly from TObject without including unit SysUtils. Unlike TObject the Exception class is nothing special as far as the compiler is concerned.

Regards,
Sven
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20120401/c8ca0a9d/attachment.html>

Reply by email

waldo kitty
to Jürgen Hestermann: Why isn't this simply added to the source files (compiler switches)? It would be much…
J?rgen Hestermann wrote 6 lines
Mattias Gaertner schrieb: > Packages allow to share ppu files. You don't have to recompile > the LCL for every project. Each package has its own directory where its > ppu files are stored. That's the concept of units. I just wonder why this is/was not enough.

but lazarus packages offer a great deal more as has already been described ;)

what else needs be pointed out???

Reply by email

Mattias Gaertner
to Marco van de Voort: TP Object syntax was perfectly valid oop. It provided mechanisms for all important OOP…
Show quoted text 13 lines
On Sun, Apr 01, 2012 at 12:52:02PM +0200, Mattias Gaertner wrote: > > OOP was already implemented in Borland Pascal. > > AFAIK this was only the "object" syntax, not the "class" syntax. IMO > the "object" syntax is too limited to be called true OOP. TP Object syntax was perfectly valid oop. It provided mechanisms for all important OOP features: 1. combining data and behaviour (code) 2. instantiation - one could instantiate multiple objects 3. encapsulation - private, public 4. polymorphism - provided by inhertiance + virtual methods.

Ah, I thought the virtual methods were missing in TP.

Thanks.

Mattias

Reply by email

Jürgen Hestermann
to Martin: I think, this means looking at 2 issues. 1) using grids, but without any platform/GUI…
Actually the basic concept of a unit is use it all or nothing.

This is not the concept of units but it seems to be a restriction of interfaces (as I now read a bit more about them). Units were introduced as libraries of functions and other declarations and that's the way I am using them. When I use SysUtils I also don't use all functions this unit implements. With smartlinking it should not even affect file size much. The unit concept was one of the main reasons for the success of the Borland compilers to overcome the splitting (and inconsistency) of interface (header files) and implementation (object files). Units are a merge of both and with the uses clause in them the compiler should be able to resolve all dependencies easily.

So by using Grids, you should expect all the platform/GUI dependent

stuff to end up in your application.

I am not even aware of all the platform/GUI dependent stuff. I just wanted to use TStringGrid types. Do I need to study the whole LCL in detail to write programs with Lazarus? It seems so.

And there are cases where smart-linking does not work. And you

encountered one. Some of the methods, of some classes in Grids can not be smart linked (IIRC virtual/overridden class methods, maybe all virtual/overridden).

Smartlinking is not the issue here (because that only affects the size of the file) but it seems that the concept of virtual methods broke the mechanism of units.

For this cases the "NoGui" widgetset exists. It provides (or should

provide) empty methods for this.

But how should I know that this is necessary? I used a simple unit in a console application. And the error messages gave no hint what is wrong.

In theory that could be changed (like a lot of thinks *could* be

done). In practise this may never happen (if only due to time available...). A re-design that big could have a lot of other side effects (which probably could all be remedied). But the cost might just be to high. (Yet I guess, if someone wants to step forward....)

Ok, I know this now. The solution in my case will be that I create 2 general purpose units: One for all programs and one for graphical programs only.

Originally a default implementation (a class wit abstract methods)

did exist, so using grids, without interfaces would compile.

- If the code was not called: good - If by some chance it was called (even totally unexpected): crash

Can the compiler no longer determine whether code will be executed or not? Then this is no longer Pascal. It sounds as if we are talking about C. All the pitfalls that existed in C now even creap into Pascal (at least it looks like this for me).

Reply by email

Jürgen Hestermann
to Hans-Peter Diettrich: Many languages have problems with e.g. multi-platform issues or, in case of Lazarus, with…
Many languages have problems with e.g. multi-platform issues or, in

case of Lazarus, with multiple implementations (of the widgetset), selectable at build time. The same for (third-party) libraries, which may or may not come with source code. That's why features like "packages" have been invented, to overcome such management problems (search paths...). Of course everybody can manage that himself, writing and updating Makefiles etc., but then he has no assistance by other tools (expect written by himself).

Of course, if projects get larger, additional concepts may be needed to handle them. But this should not affect other existing well established concepts (like units). There are lots of people outside that do not need any of the more sophisticated concepts but only want to have a tool at hand for writing one person projects.

IIRC your case is somewhat non-standard, because you use an

*abstract* class. In such an case *every* user has to indicate the unit or package, where that abstract interface is implemented.

I was not even aware of this fact nor would I have known that special provisions are needed in this case.

Reply by email

Martin
to Jürgen Hestermann: This is not the concept of units but it seems to be a restriction of interfaces (as I now…
J?rgen Hestermann wrote 8 lines
Martin schrieb: > So by using Grids, you should expect all the platform/GUI dependent stuff to end up in your application. I am not even aware of all the platform/GUI dependent stuff. I just wanted to use TStringGrid types. Do I need to study the whole LCL in detail to write programs with Lazarus? It seems so.

Well the "whole LCL" seems exaggerated, but yes, in this case I can confirm you need more knowledge, as may seem desirable.

Note: Just adding interfaces only hides the issue. It can (or may in future) mean a lot of code added to your app. If you add interfaces, then you must make sure to use the NoGUI widgetset, to avoid that.

In so far, it is actually "good" (compared to no feedback) that it fails, as it gives you the feedback something undesirable is about to happen.

Better/Correct would be a proper message, asking what to do. (Well, that is, as I wrote, subject to contribution)

Show quoted text 9 lines
> And there are cases where smart-linking does not work. And you encountered one. Some of the methods, of some classes in Grids can not be smart linked (IIRC virtual/overridden class methods, maybe all virtual/overridden). Smartlinking is not the issue here (because that only affects the size of the file) but it seems that the concept of virtual methods broke the mechanism of units.

Well the size of the file, and which parts of the unit are used appear to have a relationship.
Also the smartlinking issue is only one possible explanation.

But the error message is clear: platform dependent code is included.

Show quoted text 5 lines
> For this cases the "NoGui" widgetset exists. It provides (or should provide) empty methods for this. But how should I know that this is necessary? I used a simple unit in a console application. And the error messages gave no hint what is wrong.

Well it may need to be added to documentation.

Same applies if you use TTimer, it is widgetset dependent. Using a component or a unit, requires the user to check what the requirements are.
Just because some are self explaining, does not mean that all have to be.

For all I can see: You may have a case about missing documentation

In any case:
as said before, there is no rejection about the fact that it could be improved. (subject to someone wanting to do the work)

Reply by email

Alberto Narduzzi
to Jürgen Hestermann: This is not the concept of units but it seems to be a restriction of interfaces (as I now…
Do I need to study the whole LCL in detail to write programs with Lazarus? It seems so.

no, you don't need indeed to study it all, but a little understanding may help.

But how should I know that this is necessary? I used a simple unit in a console application. And the error messages gave no hint what is wrong.

the main issue is that you used code for the GUI (LCL) in a console application. Then the IDE and the compiler couldn't have helped you better. It is a good practice not to mix "specific" code; you may understand that a function max(a: integer; b: integer) is a little different from another like max(a: TSpinEdit; b: TSpinEdit)...
(I don't even know if the class names are correct; just in case, please forgive me).
If you had done this (using IFDEFs I mean) correctly since the beginning, you would probably never have faced the issue...

Show quoted text 9 lines
> Originally a default implementation (a class wit abstract methods) did exist, so using grids, without interfaces would compile. > - If the code was not called: good > - If by some chance it was called (even totally unexpected): crash Can the compiler no longer determine whether code will be executed or not? Then this is no longer Pascal. It sounds as if we are talking about C. All the pitfalls that existed in C now even creap into Pascal (at least it looks like this for me).

Again, as many have said already, it's time you become more familiar with abstract classes.
This has nothing to do with C (good or bad) inheritance (in terms of language design, not OO programming). Abstract classes behave like this. Full stop. Either you implement them, or don't use fact that INTERFACES is needed is just to help you with an easy "uses INTERFACES" instead of forcing you to write the whole implementation for it.

And don't come back "nobody told me, neither the IDE or the compiler did", because this leads to the INITIAL, MANDATORY, USE OF IFDES for your code.

Cheers, A.

Reply by email

Alberto Narduzzi
to Jürgen Hestermann: This is not the concept of units but it seems to be a restriction of interfaces (as I now…

Just forgot one simple thing:

If you code compiled and worked good under Delphi, that is because Delphi is platform specific (that is, Windows specific) hence the unit GRIDS already had its implementation completely done; and unit GRIDS in Delphi may not be made of abstract just hit the wrong unit at the wrong time; but at least now things may begin to get easier.

Again, cheers,
AN

Reply by email

Marco van de Voort
to Mattias Gaertner: On Sun, 1 Apr 2012 16:09:22 +0200 Ah, I thought the virtual methods were missing in TP.…
Mattias Gaertner wrote 12 lines
> > AFAIK this was only the "object" syntax, not the "class" syntax. IMO > > the "object" syntax is too limited to be called true OOP. > > TP Object syntax was perfectly valid oop. It provided mechanisms for all > important OOP features: > > 1. combining data and behaviour (code) > 2. instantiation - one could instantiate multiple objects > 3. encapsulation - private, public > 4. polymorphism - provided by inhertiance + virtual methods. Ah, I thought the virtual methods were missing in TP.

No. Heavily used in Turbo Vision. Only difference is that it does not know the virtual - override distinction, both are flagged with "override;".

For me if I go from TV to *CL, the difference can be felt more that TV has a lot of pchar trickery (to workaround shortstring limits and because it is a C++->Pascal port), and because in TV you have to write code to stream the objects and separately register them.

(the registration of an object for streaming requires you to pass pointers to the read and write methods, the framework makes sure they are properly called using self etc)

The event system delegation is also slightly different, but harder to describe that from memory.

Reply by email

Jürgen Hestermann
to Alberto Narduzzi: Just forgot one simple thing: If you code compiled and worked good under Delphi, that is…
You just hit the wrong unit at the wrong time; but at least now things may begin to get easier.

That's what I hoped so often with Lazarus but then yet another peculiarity hit me. This is especially frustrating because I never use the platform independend part of it. I only have the drawbacks but not the benefit (yet). I just imagine a young teenager would be confronted with all pupil.

Reply by email

Vincent Snijders
to Jürgen Hestermann

Op 3 april 2012 07:10 heeft J?rgen Hestermann
het volgende geschreven:

Show quoted text 10 lines
Alberto Narduzzi schrieb: > You just hit the wrong unit at the wrong time; but at least now things may > begin to get easier. That's what I hoped so often with Lazarus but then yet another peculiarity hit me. This is especially frustrating because I never use the platform independend part of it. I only have the drawbacks but not the benefit (yet). I just imagine a young teenager would be confronted with all this at school. Poor pupil.

With this difference:
* less whining
* he is used to learning new things and picks it up quicker.

VIncent

Reply by email

Bart
to Jürgen Hestermann: That's what I hoped so often with Lazarus but then yet another peculiarity hit me. This…
J?rgen Hestermann wrote 5 lines
That's what I hoped so often with Lazarus but then yet another peculiarity hit me. This is especially frustrating because I never use the platform independend part of it. I only have the drawbacks but not the benefit (yet). I just imagine a young teenager would be confronted with all pupil.

I come from TP, Delphi, and now Lazarus.
I consider myself an amateur, barely above the novice level, but I have learned over the past years, that it makes sense to use sepreate units (or ifdef them) for GUI (and thus possibly widgetset) related code and "pure pascal" (as in: non-GUI non-LCL).
IMHO it also makes cleaner code.

Use the appropriate tool to develop LCL applications (the Lazarus IDE), don't use LCL code in console programs.

If you would have learned the same over the years, you would never had this problem.
Your whole attitude in this thread is not very learnable.

Bart

Reply by email

Jürgen Hestermann
to Bart
Your whole attitude in this thread is not very learnable.

What an arrogant attitude!
Imagine that people exist who cannot effort the time (as you propably had/have) to spend theirs live on Lazarus only.

Reply by email

Michael Schnell
to Bart: I come from TP, Delphi, and now Lazarus. I consider myself an amateur, barely above the…
Bart wrote
I have learned over the past years, that it makes sense to use sepreate units (or ifdef them) for GUI (and thus possibly widgetset) related code and "pure pascal" (as in: non-GUI non-LCL).

The "separating GUI and business code" paradigm is under permanent discussion in the software industry since years.

Separation is very advantages for large and/or "professional" projects.

But it contradicts the idea of "RAD" (Rapid Application Development) that initially drove the invention of Delphi.

Same is very useful for projects dedicated to starting, learning/teaching, prototyping, testing Pascal code, testing attached devices, staying small, etc. IMHO this is true by far the most projects ever started.

Very unfortunately many 3rd party products available for free or payed don't adhere to the "separating GUI and business code" paradigm.

Unfortunately many projects start "small" and at some point get so "big" that separating GUI and business code would be appropriate, but with an advanced project, the effort is a lot harder to do.

This is especially true if it it turns out that the final product needs to be used as a service/daemon.

Here the upcoming "Custom Drawn" Widget set some day might help to allow for some kind of "GUI remoting", and by simply switching the Lazarus Widget Type the GUI can be cut off.

-Michael

Reply by email

Jürgen Hestermann
to Michael Schnell
Unfortunately many projects start "small" and at some point get so

"big" that separating GUI and business code would be appropriate, but with an advanced project, the effort is a lot harder to do.

Of course, it would always be better to do it right in the first place. But often it is unknown how a project evolves and it may also be unknown in which way a project should be splitted (it's not only GUI and "the rest"). So it can be wasted time when investing more than needed to get a program running. I don't think that in sum it needs more time to do a rebuilt later.

The important think IMO is, that *if* a project grows and *if* one realizes that something needs rebuilding that then this time has to be available and that a rebuilt has to be done. I often changed complex parts of programs in a way I could not of course the time for bug fixing should be available too.

Reply by email

Alberto Narduzzi
to Michael Schnell: The "separating GUI and business code" paradigm is under permanent discussion in the…
Separation is very advantages for large and/or "professional" projects.

separation, as you call it, is simply a good-design practice; no matter whether the project is small or big.
I quite don't believe (allow me this simple paragon) you would mix your winter and summer clothing in the same bag; and bring the very same bag with you to the beach and to the mountains...

But it contradicts the idea of "RAD" (Rapid Application Development) that initially drove the invention of Delphi.

That's simply not true. a RAD tool can help you in many ways, but your code (your CODE) still needs to be hand-written. And your CODE generally is more likely to be NON-GUY (or not so strictly GUY) related. Just to bring in a name every developer at least one time in his life has come across: the unit "utils.pas" had better be GUY-independent; as I doubt you would need a lot of graphic bells-and-whistles just to be able to use the function trimRight(s: string): String; Or do you...?

Same is very useful for projects dedicated to starting, learning/teaching, prototyping, testing Pascal code, testing attached devices, staying small, etc. IMHO this is true by far the most projects ever started.

this may indeed be the one and only place where you could at least not bother with differences between GUY and NON-GUY environments. True is that nowadays NON-GUY envs. tend to disappear; but you need to remember that FP is meant to be portable to (any) environment, including embedded systems; where this difference is still alive and kicking.

Very unfortunately many 3rd party products available for free or payed don't adhere to the "separating GUI and business code" paradigm.

Hence I wonder why some people don't complain after having paid for them...

Unfortunately many projects start "small" and at some point get so "big" that separating GUI and business code would be appropriate, but with an advanced project, the effort is a lot harder to do.

the problem must be approached the other way around... Anyway, separating GUY code from NON-GUY is not such a big task; you only need to know your tools. Or say, classes... what they do and what not. The software is your tool, your instrument, and you better know it very well... indeed, I'd dare say that it's your due.

This is especially true if it it turns out that the final product needs to be used as a service/daemon.

Sic. I'd; and probably not only me... ;-) probably kill you (but just cutting your hands would probably do as well), shall you implement a daemon with some dependencies on text/graphic specific library...

Here the upcoming "Custom Drawn" Widget set some day might help to allow for some kind of "GUI remoting", and by simply switching the Lazarus Widget Type the GUI can be cut off.

Sorry, this one I cannot catch... :-O

Cheers, A.

Reply by email

Michael Schnell
to Alberto Narduzzi
Alberto Narduzzi wrote 5 lines
True is that nowadays NON-GUY envs. tend to disappear; but you need to remember that FP is meant to be portable to (any) environment, including embedded systems; where this difference is still alive and kicking.

Embedded stuff, CGI, Daemons/Services you name it.

Since years, I always advocated that it should be possible to do non-GUI software in a decent way. But here, Lazarus is severely lacking support: there is _no_ Widget type that allows for normal "Delphi-Type" event driven programming style, without requiring a GUI binding. (Because no "Main Loop" and no event queue for timer- or thread generated events is implemented.) Of course you can use a GUI enabled Widget Type and just avoid doing GUI calls, but in an environment without the system providing the appropriate GUI API, this program will simply not run. (With the upcoming "CustomDrawn" Widget Type it might be possible to create a GUI-free variant.)

-Michael

Reply by email

Michael Schnell
to Alberto Narduzzi: separation, as you call it, is simply a good-design practice; no matter whether the…
Alberto Narduzzi wrote
Sorry, this one I cannot catch... :-O

"CustomDrwan" allows for intercepting the calls to the GUI at a layer quite near to the system API. So you can (in a sick way, from behind, at least technically) separate the business code from the GUI even in an already finished project. At least this should allow for switching off the GUI altogether.

-Michael

Reply by email

Mattias Gaertner
to Michael Schnell: Embedded stuff, CGI, Daemons/Services you name it. Since years, I always advocated that…
Show quoted text 10 lines
On 04/04/2012 10:20 PM, Alberto Narduzzi wrote: > > True is that nowadays NON-GUY envs. tend to disappear; but you need to > remember that FP is meant to be portable to (any) environment, > including embedded systems; where this difference is still alive and > kicking. Embedded stuff, CGI, Daemons/Services you name it. Since years, I always advocated that it should be possible to do non-GUI software in a decent way. But here, Lazarus is severely lacking support:

And since years you are told that Lazarus adds GUI to the non GUI stuff in FPC.
No gui stuff was never the goal of the LCL.

Show quoted text 8 lines
there is _no_ Widget type that allows for normal "Delphi-Type" event driven programming style, without requiring a GUI binding. (Because no "Main Loop" and no event queue for timer- or thread generated events is implemented.) Of course you can use a GUI enabled Widget Type and just avoid doing GUI calls, but in an environment without the system providing the appropriate GUI API, this program will simply not run. (With the upcoming "CustomDrawn" Widget Type it might be possible to create a GUI-free variant.)

Mattias

Reply by email

Michael Schnell
to Mattias Gaertner
Mattias Gaertner wrote
And since years you are told that Lazarus adds GUI to the non GUI stuff in FPC. No gui stuff was never the goal of the LCL.

I don't blame anybody on this, but it is as it is, and the fact that it "never was the goal" does not mean that it does not make sense for certain applications.

You do know that I started to take on the task and would have continued creating such a Widget Type, but stopped, as the company I work for decided that the product design asking for this should not be started in the near future.

Now the CustomDrawn Widget Type seems to be done in a way that a rather low level hook for cutting off the local GUI binding is provided and doing an "active" No-GUI" (or a remote-GUI) variant should be possible without huge effort and without inappropriate copying large part of the Code from some other Widget Type.

Maybe in fact I finally might be able to do this as a hobby project.

-Michael

Reply by email

Hans-Peter Diettrich
to Michael Schnell: Embedded stuff, CGI, Daemons/Services you name it. Since years, I always advocated that…
Show quoted text 14 lines
On 04/04/2012 10:20 PM, Alberto Narduzzi wrote: > > True is that nowadays NON-GUY envs. tend to disappear; but you need to > remember that FP is meant to be portable to (any) environment, > including embedded systems; where this difference is still alive and > kicking. Embedded stuff, CGI, Daemons/Services you name it. Since years, I always advocated that it should be possible to do non-GUI software in a decent way. But here, Lazarus is severely lacking support: there is _no_ Widget type that allows for normal "Delphi-Type" event driven programming style, without requiring a GUI binding. (Because no "Main Loop" and no event queue for timer- or thread generated events is implemented.)

The event handling, which you want to use, must be implemented and also must be supported by the platform and process type - else you cannot get there exists a noGUI widgetset, which implements
the message processing (for Timer...) in a non-GUI application. Otherwise you have to ask the FPC people for message support apart from a GUI.

DoDi

Reply by email

Michael Schnell
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote
AFAIR there exists a noGUI widgetset, which implements the message processing (for Timer...) in a non-GUI application.

Last time I checked the noGUI Widget Type did not support TTimer or Thread-generated Events (e.g. TThread.Synchronize(), TApplication.QueuAsyncCall() ) which both are essential to construct event driven applications

Otherwise you have to ask the FPC people for message support apart from a GUI.

This has been discussed already a long time ago. As there are only very few developers than need this it's absolutely OK that the Lazarus team does not dedicate their valuable resources on this issue. I would have started implementing such a Widget Type, if the application I had in mind would not have been canceled by the management.

-Michael

Reply by email

Graeme Geldenhuys
to Michael Schnell: Embedded stuff, CGI, Daemons/Services you name it. Since years, I always advocated that…
Michael Schnell wrote 5 lines
Since years, I always advocated that it should be possible to do non-GUI software in a decent way. But here, Lazarus is severely lacking support: there is _no_ Widget type that allows for normal "Delphi-Type" event driven programming style, without requiring a GUI binding. (Because no "Main Loop"

Simply use FreeVision (included with FPC) and be happy with the late 80's style console-type software. :)

Regards, ? - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://fpgui.sourceforge.net

Reply by email

Unknown author
to Michael Schnell: Last time I checked the noGUI Widget Type did not support TTimer or Thread-generated…
Michael Schnell wrote 8 lines
On 04/05/2012 02:05 PM, Hans-Peter Diettrich wrote: > AFAIR there exists a noGUI widgetset, which implements the message > processing (for Timer...) in a non-GUI application. Last time I checked the noGUI Widget Type did not support TTimer or Thread-generated Events (e.g. TThread.Synchronize(), TApplication.QueuAsyncCall() ) which both are essential to construct event driven applications

TThread.Synchronize works perfectly in any kind of application outside of the LCL.

The main thread just has to call CheckSynchronize at regular intervals. (which is what the LCL does for you).

Michael.

Reply by email

Michael Schnell
to Unknown author
Show quoted text 8 lines
TThread.Synchronize works perfectly in any kind of application outside of the LCL. The main thread just has to call CheckSynchronize at regular intervals. (which is what the LCL does for you).

Of course I do know this.

But "regular intervals" (aka polling) is not a good idea. For a decent application (e.g. embedded stuff on a low performance hardware) you need to do a decent event scheduling. This means that the main thread needs to go to sleep via an OS API call (to completely free the CPU for other threads or external tasks), and that the sleeping main thread needs to be woken up (by means of en OS API call) at once if an event (may same be thrown by a timer, a Thread or a GUI action) (to allow for the lowest possible latency).

This is not trivial at all and worth being provided by a commonly used library instead necessary to be re-implement with any project. (This is just a statement, not a request !)

The LCL does this quite nicely for all GUI enabled widget set, but not for noGUI and friends. But: see giulianos contribution the CustomDrawn mailing list.

-Michael

Reply by email

Michael Van Canneyt
to Michael Schnell
Michael Schnell wrote 12 lines
On 04/05/2012 02:37 PM, wrote: > > > TThread.Synchronize works perfectly in any kind of application outside of > the LCL. > > The main thread just has to call CheckSynchronize at regular intervals. > (which is what the LCL does for you). > Of course I do know this. But "regular intervals" (aka polling) is not a good idea.

The LCL does just that: polling.

If no events arrive, checksynchronize is not called.

There is the WakeMainThread function to try and force an event, but this can be called outside the LCL as well, thus achieving the same effect.

There really is no difference between the LCL or a non-LCL application in this regard.

Michael.

Reply by email

Michael Schnell
to Michael Van Canneyt
Michael Van Canneyt wrote
The LCL does just that: polling....

With not embedded application (which of course is the main target for LCL application) Latency and performance optimizing is not a real issue, so this certainly is good enough.

But at least on Windows this is certainly not necessary, as all events are handled by the Windows message queue and automatically wake the main thread waiting for an events in the appropriate API call.

With other widget Types, that seemingly needs to have multiple queues this might be a lot more complicated.

-Michael

Reply by email

Michael Van Canneyt
to Michael Schnell
Michael Schnell wrote 9 lines
On 04/05/2012 03:25 PM, Michael Van Canneyt wrote: > The LCL does just that: polling.... With not embedded application (which of course is the main target for LCL application) Latency and performance optimizing is not a real issue, so this certainly is good enough. But at least on Windows this is certainly not necessary, as all events are handled by the Windows message queue and automatically wake the main thread waiting for an events in the appropriate API call.

And how does the application see the events ?

Exactly, by polling Windows to see if there is an event available...

('polling' being the operative word here)

Events do not automagically appear in your application, even under windows.

They are not interrupts.

Michael.

Reply by email

Michael Schnell
to Michael Van Canneyt
Michael Van Canneyt wrote
Events do not automagically appear in your application, even under windows. They are not interrupts.

AFAIK, in Windows, the Application main thread can call an API function to wait for the next message. Here it uses no CPU cycles and when a message in the queue for that thread arrives from what origin ever, the thread is activated at once and will run according to it's priority thus minimizing the latency to the limit that the OS and the other running tasks allow. I don't see why a "timeout" would necessarily be enabled to return from that call (providing real polling), as there should be no notifications to the main thread that don?t run through the queue, generating such a message and waking the Main Thread.

Of course if the main thread is just working on an event, when a new event is fed to the queue, it will first finish its current work (unless it explicitly calls "Application.ProcessMessages") before it is ready to handle the new event. But this is just how a single-threaded application needs to work.

I would not call this "polling", as the "main Loop" only runs at max a single turn for each event, while the process sleeps until the next event arises.

Maybe GTK does not allow for such a design, though, because not all events can be run though a single queue with embedded waiting/waking functionality.

No idea at all regarding fpGUI/X11 etc.

-Michael

Reply by email

Michael Van Canneyt
to Michael Schnell
Michael Schnell wrote 7 lines
On 04/05/2012 03:39 PM, Michael Van Canneyt wrote: > Events do not automagically appear in your application, even under windows. > > They are not interrupts. AFAIK, in Windows, the Application main thread can call an API function to wait for the next message.

Exactly. That is called 'polling' windows...

Show quoted text 16 lines
Here it uses no CPU cycles and when a message in the queue for that thread arrives from what origin ever, the thread is activated at once and will run according to it's priority thus minimizing the latency to the limit that the OS and the other running tasks allow. I don't see why a "timeout" would necessarily be enabled to return from that call (providing real polling), as there should be no notifications to the main thread that don?t run through the queue, generating such a message and waking the Main Thread. Of course if the main thread is just working on an event, when a new event is fed to the queue, it will first finish its current work (unless it explicitly calls "Application.ProcessMessages") before it is ready to handle the new event. But this is just how a single-threaded application needs to work. I would not call this "polling", as the "main Loop" only runs at max a single turn for each event, while the process sleeps until the next event arises.

You have a strange definition of polling.

Polling = Checking something at regular intervals.

No more, no less.

Whether or not the CPU is used a lot, or how many threads are in the application, is irrelevant for the definition, they are implementation details.

Maybe GTK does not allow for such a design, though, because not all events can be run though a single queue with embedded waiting/waking functionality.

Qt/GTK/X11 allow for this design as well.

Michael.

Reply by email

Michael Schnell
to Michael Van Canneyt
Michael Van Canneyt wrote 9 lines
Exactly. That is called 'polling' windows... ... You have a strange definition of polling. Polling = Checking something at regular intervals.

Sorry for being tense, but what has been described (and acknowledged by you) is _not_ doing something at regular intervals. The API only returns when a message arrives. some might come in some microsecond intervals and then there might be a gap of days. To me this is not "regular intervals".

Qt/GTK/X11 allow for this design as well.

So there is a possibility to feed user events to the queue in GTK ? If so, I don't understand why the GTK Widget Type (other than the Windows Widget Type) implements additional (an) queue(s) in Pascal code. (I never took a look at QT.)

-Michael

Reply by email

Unknown author
to Michael Schnell
Michael Schnell wrote 15 lines
On 04/05/2012 04:45 PM, Michael Van Canneyt wrote: > > > > Exactly. That is called 'polling' windows... > > ... > You have a strange definition of polling. > > Polling = Checking something at regular intervals. Sorry for being tense, but what has been described (and acknowledged by you) is _not_ doing something at regular intervals. The API only returns when a message arrives. some might come in some microsecond intervals and then there might be a gap of days. To me this is not "regular intervals".

Can you try to open your mind a bit and get the spirit of the definition ? Please ?

Then try this:

Polling = Asking or checking something.

This is as opposed to 'interrupts', where you're not asking, but where the environment interrupts whatever you're doing and forces you to handle the event right there and then.

The 'regular intervals' you seem to insist on, means you just put a timeout on the time you wait for your answer when polling.

Show quoted text 6 lines
> Qt/GTK/X11 allow for this design as well. So there is a possibility to feed user events to the queue in GTK ? If so, I don't understand why the GTK Widget Type (other than the Windows Widget Type) implements additional (an) queue(s) in Pascal code. (I never took a look at QT.)

Just add a file descriptor to the main loop mechanism, and write something to it from wherever you want to send an event.

Michael.

Reply by email

Henry Vermaak
to Michael Schnell: Sorry for being tense, but what has been described (and acknowledged by you) is _not_…
Michael Schnell wrote
So there is a possibility to feed user events to the queue in GTK ? If

Yes, you can add your own file descriptors for the gdk event loop to watch. So you can have the loop wake up when there's input on a network socket, for instance. You can add any new event source which can have prepare/check/dispatch/finalize functions.

You can use the glib event loop in non-gui programs, too.

so, I don't understand why the GTK Widget Type (other than the Windows Widget Type) implements additional (an) queue(s) in Pascal code. (I

Sorry, I'm not very familiar with the GTK interface code, could you point me to this additional queue?

Henry

Reply by email

Michael Schnell
to Unknown author: Can you try to open your mind a bit and get the spirit of the definition ? Please ? Then…
Then try this: Polling = Asking or checking something.

OK, if you want it that way, I'm with you now.

Show quoted text 5 lines
This is as opposed to 'interrupts', where you're not asking, but where the environment interrupts whatever you're doing and forces you to handle the event right there and then.

Interrupts are no issue here. That is a completely different concept.

Maybe the distinction I have in mind might better denoted as "busy loop" vs. "sleep until action is necessary".

The 'regular intervals' you seem to insist on,

Sorry but this was your wording I seemingly misunderstood.

Show quoted text 9 lines
means you just put a timeout on the time you wait for your answer when polling. >> Qt/GTK/X11 allow for this design as well. > Just add a file descriptor to the main loop mechanism, and write something to it from wherever you want to send an event.

Does GTK know files ?

Of course, if there is no GUI, you will use such OS API based Sync mechanisms to do a non-busy wait (there are lots more such as Pipes, Semaphores, Mutex, ...) . But if there are GUI (here GTK) events to be handled _and_ user (e.g. Thread-) originated events, you need to decide where to sleep. If sleeping in a GTK call, the "file" events will not wake up the thread; if waiting for a file, the GTK events will not wake up the thread.

So I see two solutions:

(1) Wait in one environment (e.g. GTK) and define the wait with a timeout specification. (I suppose that this is what the GTK Widget Type does. ) This implements a (partly / regular interval) busy loop polling for the other (e.g. Thread- originated) events.

(2) use an additional thread that waits for the GUI events in an appropriate API call and use same to transfer the events to the non-busy waiting Main loop. I understand that this is (a) rather complex and (b) uses up some performance when handling GUI events. But in fact this will reduce overall CPU time and the latency of non-GUI events.

So I do understand that the LCL does not implement something like (2) for good reasons.

Theses thoughts might show why I recon that the LCL does "busy loop" - polling in GTK but not (necessarily) in Windows.

Thanks for your time.
-Michael

Reply by email

Michael Schnell
to Henry Vermaak: Yes, you can add your own file descriptors for the gdk event loop to watch. So you can…
Henry Vermaak wrote
Yes, you can add your own file descriptors for the gdk event loop to watch.

I did not know about this concept. Maybe this is a perfect solution. If so, why does (or did when I checked quite a long time ago) GT2 implement at least one additional event queue in Pascal code =

You can use the glib event loop in non-gui programs, too.

Yes I know this but I understood that this can't easily be synced with the gdk queue (thus preventing an "general" implementation). Maybe your hint above shows this way.

-Michael

Reply by email

Sven Barth
to Michael Schnell: Of course I do know this. But "regular intervals" (aka polling) is not a good idea. For a…
Michael Schnell wrote 19 lines
On 04/05/2012 02:37 PM, wrote: > > > TThread.Synchronize works perfectly in any kind of application outside of > the LCL. > > The main thread just has to call CheckSynchronize at regular intervals. > (which is what the LCL does for you). > Of course I do know this. But "regular intervals" (aka polling) is not a good idea. For a decent application (e.g. embedded stuff on a low performance hardware) you need to do a decent event scheduling. This means that the main thread needs to go to sleep via an OS API call (to completely free the CPU for other threads or external tasks), and that the sleeping main thread needs to be woken up (by means of en OS API call) at once if an event (may same be thrown by a timer, a Thread or a GUI action) (to allow for the lowest possible latency).

If you can accept a main thread that only handles Synchronize events then you can call CheckSynchronize with a very high timeout value (on Windows you can also use INFINITE=DWord(-1)). CheckSynchronize internally (platform independently!) waits for an event that is set once Synchronize is called (this event is reset after CheckSynchronize is done). So you basically utilize the operating system functionality.

Please note that only on Windows you get a true infinite wait while on systems based on Posix threads always a timeout wait is used (this could be circumvented if for "DWord(-1)" the non-timeout wait variant of the RTL would be used, but I don't know the potiential implications that such a change may have - though I also don't know how exactly CheckSynchronize will behave on Posix systems if you call it with INFINITE as argument).

Regards,
Sven

Reply by email

Henry Vermaak
to Michael Schnell: I did not know about this concept. Maybe this is a perfect solution. If so, why does (or…
Michael Schnell wrote 7 lines
On 04/05/2012 06:03 PM, Henry Vermaak wrote: > > Yes, you can add your own file descriptors for the gdk event loop to > watch. I did not know about this concept. Maybe this is a perfect solution. If so, why does (or did when I checked quite a long time ago) GT2 implement at least one additional event queue in Pascal code =

Got any reference to this code?

Show quoted text 5 lines
> You can use the glib event loop in non-gui programs, too. Yes I know this but I understood that this can't easily be synced with the gdk queue (thus preventing an "general" implementation). Maybe your hint above shows this way.

Explain why you think it can't be integrated with other loops? Glib has been synced with many things (libev, zeromq, qt, etc).

Henry

Reply by email

Hans-Peter Diettrich
to Michael Schnell: Sorry for being tense, but what has been described (and acknowledged by you) is _not_…
Show quoted text 13 lines
On 04/05/2012 04:45 PM, Michael Van Canneyt wrote: > > > > Exactly. That is called 'polling' windows... > > ... > You have a strange definition of polling. > > Polling = Checking something at regular intervals. Sorry for being tense, but what has been described (and acknowledged by you) is _not_ doing something at regular intervals.

How do you think to implement "regular intervals", when you need a timer *message* for that purpose?

Perhaps we should distinguish between *blocking and non-blocking* polling. You seem to mention non-blocking polling, which can be used with multiple independent sources. The blocking version, as used to poll the event queue, puts the thread asleep until the event (new message) occurs.

DoDi

Reply by email

Hans-Peter Diettrich
to Graeme Geldenhuys: Simply use FreeVision (included with FPC) and be happy with the late 80's style…
Show quoted text 9 lines
On 5 April 2012 09:38, Michael Schnell wrote: > Since years, I always advocated that it should be possible to do non-GUI > software in a decent way. But here, Lazarus is severely lacking support: > there is _no_ Widget type that allows for normal "Delphi-Type" event driven > programming style, without requiring a GUI binding. (Because no "Main Loop" Simply use FreeVision (included with FPC) and be happy with the late 80's style console-type software. :)

There exist more process types (Windows services, servers? ...), which are event-driven but don't have a GUI.

DoDi

Reply by email

waldo kitty
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 12 lines
Graeme Geldenhuys schrieb: > On 5 April 2012 09:38, Michael Schnell wrote: >> Since years, I always advocated that it should be possible to do non-GUI >> software in a decent way. But here, Lazarus is severely lacking support: >> there is _no_ Widget type that allows for normal "Delphi-Type" event driven >> programming style, without requiring a GUI binding. (Because no "Main Loop" > > Simply use FreeVision (included with FPC) and be happy with the late > 80's style console-type software. :) There exist more process types (Windows services, servers? ...), which are event-driven but don't have a GUI.

so... noGUI? maybe... :?

i also have to dig back to find an unit/procedure that confused me... a command line processing one... it seems that it is only available with an application project and not via a non-GUI one... i think... it seems to me that anything available to a GUI app, like command line params, should also be available to a non-GUI one... i have been meaning to bring this up in the past but have had other projects in the way... i won't hijack this thread any further than this, though and will try to bring this up shortly... but first, i need to figure out what lib it is in ;) :P ;)

Reply by email

zeljko
to Michael Schnell: Sorry for being tense, but what has been described (and acknowledged by you) is _not_…
Michael Schnell wrote 6 lines
> Qt/GTK/X11 allow for this design as well. So there is a possibility to feed user events to the queue in GTK ? If so, I don't understand why the GTK Widget Type (other than the Windows Widget Type) implements additional (an) queue(s) in Pascal code. (I never took a look at QT.)

Because gtk2 code is taken from gtk1 which needed such stuff for proper functioning. Gtk2 does not use old iteration style anymore, yes there's still queue for resizing and painting, but I don't won't to remove it or touch it atm (if ever). Gtk3 will have pure implementation without need of any queue on lcl side. Qt implementation is cleanest one - no private queues or similar stuff.
Besides that , do not forget that all non-windows widgetsets must emulate stuff to be winapi and delphi compatibile (events, events order etc etc).

zeljko
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20120406/8f8d5324/attachment-0001.html>

Reply by email

Michael Schnell
to Henry Vermaak: Got any reference to this code? Explain why you think it can't be integrated with other…
Explain why you think it can't be integrated with other loops? Glib has been synced with many things (libev, zeromq, qt, etc).

When thinking, over the weekend I, seem to now top have understood, that I misread your suggestion and that it's vice-versa than I first go it:

GTK does not "know about files", but it provides a file handle that can used in "select()" or "epoll()" OS-API calls to allow for waiting on GTK generated events at the same time with additional events that provide "file" actions. Of course a thread communication (such as "TThread.Synchronize() and "Application.Queue AsyncCall()) can be done using File events usable in select() or epoll().

Thus the "busy polling" using a timeout to do a periodic polling cycle, can easily be avoided and I do hope that the Widget Type code in fact works that way.

Thanks,
-Michael

(Oh course I now also see that the term "poll" is used in the name "epoll", and this of course is provided explicitly for avoiding "busy polling". :-[ )

Reply by email

Michael Schnell
to zeljko: Because gtk2 code is taken from gtk1 which needed such stuff for proper functioning. Gtk2…

I see.

Thanks !

If the GTK3 Widget Type does not need for Pascal based queues for things like "TThread.Synchronize()" or "Application.QueueAsyncCall" the GTK3 API would need to provide a way to insert user program created events in the external queue (such as Windows does).

If so: good.

If not so: using select() or epoll() to wait for events from both an external and an internal queue is a perfect solution as well.

-Michael

Reply by email