Sign in Join

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

Mailing lists / fpc-pascal / 2009-11

const records passed incorrectly

31 messages · 9 people ·

Reply by email Subscribe to this list Your subscription

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

Anthony Walter

Hi all. I am new to fpc and linux in general, though I do have a long time experience with Delphi.

I was writing some code basic system (using the libc library) when I ran across the following problem .. some code:

const
  libc = 'libc.so.6';
type
  TTimeSpec = record
    Sec: Cardinal;  { Seconds }
    NSec: Cardinal; { Nanoseconds }
  end;
  PTimeSpec = ^TTimeSpec;
function nanosleep(const RequestedTime: TTimeSpec; Remaining:
PTimeSpec): Integer; cdecl; external libc;

The problem with fpc and the above import is with the RequestedTime parameter, declared as a const record. In Delphi declaring a const record parameter cause the compiler to generate code to pass the record by reference (that is to say passing the address). In fpc, however this is not happening.

My question is why. Why isn't fpc generating the code to pass a const record as a reference?

I can find tons of WinAPI code where records are passed as const references by Delphi. I see this issue causing me some headaches as I port my Delphi code to run across platforms using fpc.

Reply by email

Michael Van Canneyt
to Anthony Walter
Anthony Walter wrote 24 lines
Hi all. I am new to fpc and linux in general, though I do have a long time experience with Delphi. I was writing some code basic system (using the libc library) when I ran across the following problem .. some code: const libc = 'libc.so.6'; type TTimeSpec = record Sec: Cardinal; { Seconds } NSec: Cardinal; { Nanoseconds } end; PTimeSpec = ^TTimeSpec; function nanosleep(const RequestedTime: TTimeSpec; Remaining: PTimeSpec): Integer; cdecl; external libc; The problem with fpc and the above import is with the RequestedTime parameter, declared as a const record. In Delphi declaring a const record parameter cause the compiler to generate code to pass the record by reference (that is to say passing the address). In fpc, however this is not happening.

No.

It is nowhere written in the Delphi specs that const parameters are passed by reference. It is often so, but is by no means guaranteed.

If you want to pass it as a reference, you should use var. Not const.

Const means that the called procedure does not change the contents. The compiler may then decide to pass it by reference if it is more advantageous to do so, but it is not a rule that this is done.

Michael.

Reply by email

Anthony Walter
to Michael Van Canneyt

Actually the help does. The first thing I did when I got to work with morning was top open my Delphi 7 help file and typed "const" then choose the topic "constant (const) parameters".

Quote:

"Using const allows the compiler to optimize code for structured- and string-type parameters."

Using const with string type and structured types causes a known optimization to pass references rather than copies on the stack. The key is Delphi checks code in the callee making sure you don't try to write to the const parameter.

This is useful not only for speed purposes, but for operability with C code like below (take from the Windows Platform SDK help file):

BOOL RectVisible(
HDC hdc, // handle of the device context
CONST RECT *lprc // address of rectangle structure

   );

Delphi declares this import as follows:

function RectVisible(DC: HDC; const Rect: TRect): BOOL; stdcall;

Note the "const Rect: TRect"

Now I wrote an example to test the differences between FPC (version 2.2.4) and Delphi (version 7). I found something interesting, please read the results at the bottom.

Code:

program test;
{$APPTYPE CONSOLE}
type
  TRect = record
    Left, Top, Right, Bottom: Integer;
  end;
procedure A(const R: TRect; P: Pointer);
begin
  if @R = P then
    WriteLn('R refers to a reference on the stack')
  else
    WriteLn('R is a structure on the stack');
end;
procedure B;
var
  R: TRect;
begin
  A(R, @R);
end;
begin
  B;
end.

Output:

FPC: "R refers to a reference on the stack"
Delphi: "R refers to a reference on the stack"

Which is exactly correct with both compilers. So there is no problem, my original problem doesn't apply.

***** BUT *****

There is a problem with the above code on FPC when you change calling conventions of A.

If you change the calling convention to stdcall it still works, no problem. Both FPC and Delphi output "R refers to a reference on the stack."

On the other hand, changing to cdecl breaks things on the FPC side.

procedure A(const R: TRect; P: Pointer); cdecl;

Output:

FPC: "R is a structure on the stack"
Delphi: "R refers to a reference on the stack"

See, FPC is now working differently. This is causing me headaches when I am writing code to import libc (which uses cdecl).

I believe FPC is in error when it is generating code to pass const structures (which I've tested). It handles parameters one way with fastcall, stdcall, pascal (which I believe is the correct way), and a different way with cdecl.

I've tested Delphi and it always uses a reference on the stack with all calling conventions using the code above.

I've provided the information from the Delphi help file which documents this feature.

Michael Van Canneyt wrote 45 lines
On Sun, 15 Nov 2009, Anthony Walter wrote: > Hi all. I am new to fpc and linux in general, though I do have a long > time experience with Delphi. > > I was writing some code basic system (using the libc library) when I > ran across the following  problem .. some code: > > const >  libc = 'libc.so.6'; > > type >  TTimeSpec = record >   Sec: Cardinal;  { Seconds } >   NSec: Cardinal; { Nanoseconds } >  end; >  PTimeSpec = ^TTimeSpec; > > function nanosleep(const RequestedTime: TTimeSpec; Remaining: > PTimeSpec): Integer; cdecl; external libc; > > The problem with fpc and the above import is with the RequestedTime > parameter, declared as a const record. In Delphi declaring a const > record parameter cause the compiler to generate code to pass the > record by reference (that is to say passing the address). In fpc, > however this is not happening. No. It is nowhere written in the Delphi specs that const parameters are passed by reference. It is often so, but is by no means guaranteed. If you want to pass it as a reference, you should use var. Not const. Const means that the called procedure does not change the contents. The compiler may then decide to pass it by reference if it is more advantageous to do so, but it is not a rule that this is done. Michael. _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Martin Schreiber
to Michael Van Canneyt: No. It is nowhere written in the Delphi specs that const parameters are passed by…
Michael Van Canneyt wrote
It is nowhere written in the Delphi specs that const parameters are passed by reference. It is often so, but is by no means guaranteed.

There is a sentence in Delphi 7 "Language Guide" in chapter 12 "Parameters and function results" which possibly belongs to the theme: http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/programcontrolov_xml.html "
Value and constant (const) parameters are passed by value or by reference, depending on the type and size of the parameter:
[...]
Sets, records, and static arrays of 1, 2, or 4 bytes are passed as 8-bit, 16-bit, and 32bit values. Larger sets, records, and static arrays are passed as 32-bit pointers to the value. An exception to this rule is that records are always passed directly on the stack under the cdecl, stdcall, and safecall conventions; the size of a record passed this way is rounded upward to the nearest double-word boundary.
"
An example from Delphi windows.pas:
"
type

  POverlapped = ^TOverlapped;
  _OVERLAPPED = record
    Internal: DWORD;
    InternalHigh: DWORD;
    Offset: DWORD;
    OffsetHigh: DWORD;
    hEvent: THandle;
  end;
  {$EXTERNALSYM _OVERLAPPED}
  TOverlapped = _OVERLAPPED;
  OVERLAPPED = _OVERLAPPED;
  {$EXTERNALSYM OVERLAPPED}

[...]
function LockFileEx(hFile: THandle; dwFlags, dwReserved: DWORD;

  nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh: DWORD;
  const lpOverlapped: TOverlapped): BOOL; stdcall;

"
And the C++-header:
"
BOOL WINAPI LockFileEx(
__in HANDLE hFile,
__in DWORD dwFlags,
__reserved DWORD dwReserved,
__in DWORD nNumberOfBytesToLockLow,
__in DWORD nNumberOfBytesToLockHigh,
__inout LPOVERLAPPED lpOverlapped
);
"
So it is stdcall -> "An exception to this rule is that records are always passed directly on the stack" but LPOVERLAPPED is a pointer? There is a not documented special rule for const?

Please don't shot me if it does not belong to the theme. ;-)

Martin

Reply by email

Jonas Maebe
to Anthony Walter: Actually the help does. The first thing I did when I got to work with morning was top…
Anthony Walter wrote
There is a problem with the above code on FPC when you change calling conventions of A.

Const indeed behaves differently depending on the calling convention. With register and stdcall, we emulate Delphi. With mwpascal, we emulate MetroWerks Pascal. With cdecl, we emulate C compilers. In C compilers, adding "const" does not change the way the parameter is passed: they are still passed by value. There have been lots of discussions in the past about adding something like constvar or constref, but nothing has ever come from it.

Jonas

Reply by email

Anthony Walter
to Martin Schreiber: There is a sentence in Delphi 7 "Language Guide" in chapter 12 "Parameters and function…

I assume you replied so quickly you did not get the chance to read my crafted and tested reply. You may have been typing the same time I was :)

Please go back and read my message and note the tests section.

Jonas, why is FPC emulating C when it could simply follow the Delphi way and prevent these incompatibilities?

It seems to me that the most logical thing is to handle it the same in all calling conventions, which is what Delphi does (as verified through my tests).

Martin Schreiber wrote 61 lines
On Monday 16 November 2009 08:59:50 Michael Van Canneyt wrote: > > It is nowhere written in the Delphi specs that const parameters > are passed by reference. It is often so, but is by no means guaranteed. > There is a sentence in Delphi 7 "Language Guide" in chapter 12 "Parameters and function results" which possibly belongs to the theme: http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/programcontrolov_xml.html " Value and constant (const) parameters are passed by value or by reference, depending on the type and size of the parameter: [...] Sets, records, and static arrays of 1, 2, or 4 bytes are passed as 8-bit, 16-bit, and 32bit values. Larger sets, records, and static arrays are passed as 32-bit pointers to the value. An exception to this rule is that records are always passed directly on the stack under the cdecl, stdcall, and safecall conventions; the size of a record passed this way is rounded upward to the nearest double-word boundary. " An example from Delphi windows.pas: " type  POverlapped = ^TOverlapped;  _OVERLAPPED = record    Internal: DWORD;    InternalHigh: DWORD;    Offset: DWORD;    OffsetHigh: DWORD;    hEvent: THandle;  end;  {$EXTERNALSYM _OVERLAPPED}  TOverlapped = _OVERLAPPED;  OVERLAPPED = _OVERLAPPED;  {$EXTERNALSYM OVERLAPPED} [...] function LockFileEx(hFile: THandle; dwFlags, dwReserved: DWORD;  nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh: DWORD;  const lpOverlapped: TOverlapped): BOOL; stdcall; " And the C++-header: " BOOL WINAPI LockFileEx(  __in        HANDLE hFile,  __in        DWORD dwFlags,  __reserved  DWORD dwReserved,  __in        DWORD nNumberOfBytesToLockLow,  __in        DWORD nNumberOfBytesToLockHigh,  __inout     LPOVERLAPPED lpOverlapped ); " So it is stdcall -> "An exception to this rule is that records are always passed directly on the stack" but LPOVERLAPPED is a pointer? There is a not documented special rule for const? Please don't shot me if it does not belong to the theme. ;-) Martin _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Michael Van Canneyt
to Anthony Walter: Actually the help does. The first thing I did when I got to work with morning was top…
Anthony Walter wrote
Actually the help does. The first thing I did when I got to work with morning was top open my Delphi 7 help file and typed "const" then choose the topic "constant (const) parameters".

Definitely not in the printed manual of D7, which I consulted prior to typing my answer...

Show quoted text 5 lines
Quote: "Using const allows the compiler to optimize code for structured- and string-type parameters."

Yes, it says this in my manual as well, but no more and no less.

Michael.

Reply by email

Anthony Walter
to Jonas Maebe: I think that FPC's behaviour predates the existence of Delphi. Jonas

As I said in my introduction. I am new to Linux and FPC. I've used them both for maybe 8 years, but not seriously.

On the Linux side for years I've just used it for minimal compiling and a lot of web browser.

On the FPC I've fired it up from time to time over the years (and read the website, mailing lists).

None of that I consider real use, just casual poking around.

But now I am taking a serious stab at porting my Windows OpenGL game engine to a cross platform Windows, Linux, and Mac engine. I feel like I am actually doing something real with Linux and FPC for the first time.

One thing I've noticed about the FPC community which has me a somewhat apprehensive is a bit of a particular attitude I've picked up on.

A few times now I've read comments by or had conversations with people in the FPC community who have explained incompatibilities away using the phrase:

"FreePascal did this before something else so we shouldn't change"

Forgetting the whole argument about who was actually first, I have to ask what difference does it make?

Why does doing something first make it written in stone. It seems a bit childish to say, "No way, I way here first, I won't budge. You move."

Really, that attitude is quite the turn off.

There there these incompatibilities causing me to avoid language features. I'd like to use them but just won't (Operator overloading and generics come to mind), mostly because I really don't want to have ifdefs all over the place.

In my opinion, there is an incompatibility. Fix it.

Jonas Maebe wrote 14 lines
On 16 Nov 2009, at 15:01, Anthony Walter wrote: > Jonas, why is FPC emulating C when it could simply follow the Delphi > way and prevent these incompatibilities? I think that FPC's behaviour predates the existence of Delphi. Jonas _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Anthony Walter
to Florian Klaempfl

I probably should, but I've never worked on a community project before. I don't know the ins and outs of hooking up to the developer repository, getting the build environment working, discussing and submitting my changes, testing those changes, and moving them into the official version.

If anyone could provide me with links to that info you might have yourselves another human resource on the fpc team.

Florian Klaempfl wrote 8 lines
> > In my opinion, there is an incompatibility. Fix it. If you care about it, provide a usable patch. _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Michael Van Canneyt
to Anthony Walter: As I said in my introduction. I am new to Linux and FPC. I've used them both for maybe 8…
Anthony Walter wrote 33 lines
As I said in my introduction. I am new to Linux and FPC. I've used them both for maybe 8 years, but not seriously. On the Linux side for years I've just used it for minimal compiling and a lot of web browser. On the FPC I've fired it up from time to time over the years (and read the website, mailing lists). None of that I consider real use, just casual poking around. But now I am taking a serious stab at porting my Windows OpenGL game engine to a cross platform Windows, Linux, and Mac engine. I feel like I am actually doing something real with Linux and FPC for the first time. One thing I've noticed about the FPC community which has me a somewhat apprehensive is a bit of a particular attitude I've picked up on. A few times now I've read comments by or had conversations with people in the FPC community who have explained incompatibilities away using the phrase: "FreePascal did this before something else so we shouldn't change" Forgetting the whole argument about who was actually first, I have to ask what difference does it make? Why does doing something first make it written in stone. It seems a bit childish to say, "No way, I way here first, I won't budge. You move." Really, that attitude is quite the turn off.

Correct, but then the same applies to Borland/Codegear/Embarcadero.

Go ahead, and ask them to be more FPC compliant.

It'll be interesting to see their reaction.

People take such a position from Borland, but not from FPC. Why ?

This is quite ironic, because you PAY Borland and you put up with their attitudes. You don't pay FPC but you also don't want to put up with our attitudes. Where is the logic in that ? I would expect the opposite. You pay them for god's sake, so they should do your bidding...

In reality it's always the FPC team that is f*d when an incompatibility arises.

Michael.

Reply by email

Marco van de Voort
to Anthony Walter: I probably should, but I've never worked on a community project before. I don't know the…

In our previous episode, Anthony Walter said:

Show quoted text 8 lines
I probably should, but I've never worked on a community project before. I don't know the ins and outs of hooking up to the developer repository, getting the build environment working, discussing and submitting my changes, testing those changes, and moving them into the official version. If anyone could provide me with links to that info you might have yourselves another human resource on the fpc team.

http://www.stack.nl/~marcov/buildfaq.pdf

details level 0.

Reply by email

Jonas Maebe
to Anthony Walter: As I said in my introduction. I am new to Linux and FPC. I've used them both for maybe 8…
Anthony Walter wrote
"FreePascal did this before something else so we shouldn't change" Forgetting the whole argument about who was actually first, I have to ask what difference does it make?

I was merely answering your question why we do it differently than Delphi, even though Delphi is generally the de facto standard. I was trying to explain that we did not do it differently simply because our way was the right one and Delphi's way the wrong one, or out of spite or so. But it appears that you interpreted my answer in exactly the opposite sense (that we won't change it out of spite).

The main problem with changing it now would obviously be that it would break backwards compatibility with existing code. It could still be done in Delphi mode onlu, of course, but changing the behaviour of a calling convention (which is normally an ABI issue) based on a language syntax mode feels... not right.

There there these incompatibilities causing me to avoid language features. I'd like to use them but just won't (Operator overloading and generics come to mind), mostly because I really don't want to have ifdefs all over the place.

It's a lot of work to re-implement everything afterwards according to how Borland decided to implement things. Our time is finite, just like everyone else's... And generally people prefer to spend their time on implementing new features (that Borland again can add a few months/ year later using an incompatible syntax/behaviour ;) rather than on overhauling existing ones, or on Delphi features that we do not support at all yet.

In general, Delphi syntax is usually integrated/supported after a while anyway (because someone submits a patch, or because it becomes widely used and someone wants to use code that uses this feature). Like most community-driven open source projects, the way FPC evolves is primarily driven by
a) the interests of its core developers
b) the interest of other people that submit patches

There is no company (yet?) that writes FPC patches for commercially supporting Delphi developers, afaik. The closest there is, is http://wiki.freepascal.org/Bounties

Jonas

Reply by email

Anthony Walter
to Michael Van Canneyt: Correct, but then the same applies to Borland/Codegear/Embarcadero. Go ahead, and ask…

This is because Delphi belongs to is a commercial enterprise, and it is in their best interested not to bend over backwards to work with a free competing product.

The power I felt FPC has had was it's compatibility with Delphi. FPC maintained compatibility with the languages and even with the class library (SysUtils.pas, Classes.pas).

I understand it's difficult to maintain this parity between FPC and Delphi, especially when Delphi does things which seem wrong (such as they way they implemented operator overloading), but IMO keeping that parity goes is more important than ego (if that is where the problem really lays).

To Marco:

Thanks for that link. I will read that rocument and try to get started with the developer repository and build environment this week. If I have and questions (which google and my own experimentation can't answer), where would be the best place to submit them?

Michael Van Canneyt wrote 59 lines
On Mon, 16 Nov 2009, Anthony Walter wrote: > As I said in my introduction. I am new to Linux and FPC. I've used > them both for maybe 8 years, but not seriously. > > On the Linux side for years I've just used it for minimal compiling > and a lot of web browser. > > On the FPC I've fired it up from time to time over the years (and read > the website, mailing lists). > > None of that I consider real use, just casual poking around. > > But now I am taking a serious stab at porting my Windows OpenGL game > engine to a cross platform Windows, Linux, and Mac engine. I feel like > I am actually doing something real with Linux and FPC for the first > time. > > One thing I've noticed about the FPC community which has me a somewhat > apprehensive is a bit of a particular attitude I've picked up on. > > A few times now I've read comments by or had conversations with people > in the FPC community who have explained incompatibilities away using > the phrase: > > "FreePascal did this before something else so we shouldn't change" > > Forgetting the whole argument about who was actually first, I have to > ask what difference does it make? > > Why does doing something first make it written in stone. It seems a > bit childish to say, "No way, I way here first, I won't budge. You > move." > > Really, that attitude is quite the turn off. Correct, but then the same applies to Borland/Codegear/Embarcadero. Go ahead, and ask them to be more FPC compliant. It'll be interesting to see their reaction. People take such a position from Borland, but not from FPC. Why ? This is quite ironic, because you PAY Borland and you put up with their attitudes. You don't pay FPC but you also don't want to put up with our attitudes. Where is the logic in that ? I would expect the opposite. You pay them for god's sake, so they should do your bidding... In reality it's always the FPC team that is f*d when an incompatibility arises. Michael. _______________________________________________ fpc-pascal maillist  -   http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Michael Van Canneyt
to Anthony Walter
Anthony Walter wrote 13 lines
This is because Delphi belongs to is a commercial enterprise, and it is in their best interested not to bend over backwards to work with a free competing product. The power I felt FPC has had was it's compatibility with Delphi. FPC maintained compatibility with the languages and even with the class library (SysUtils.pas, Classes.pas). I understand it's difficult to maintain this parity between FPC and Delphi, especially when Delphi does things which seem wrong (such as they way they implemented operator overloading), but IMO keeping that parity goes is more important than ego (if that is where the problem really lays).

Ego is not the problem. Time is, as Jonas pointed out.

My observations were purely from a more philosophical point of view; In general we try to be Delphi compatible as much as time and backward compatibility permits.

Michael.

Reply by email

Marco van de Voort
to Anthony Walter: This is because Delphi belongs to is a commercial enterprise, and it is in their best…

In our previous episode, Anthony Walter said:

Show quoted text 6 lines
To Marco: Thanks for that link. I will read that rocument and try to get started with the developer repository and build environment this week. If I have and questions (which google and my own experimentation can't answer), where would be the best place to submit them?

The fpc-devel group and/or irc.

Reply by email

Anthony Walter
to Jonas Maebe: I was merely answering your question why we do it differently than Delphi, even though…
Jonas Maebe wrote 6 lines
I was merely answering your question why we do it differently than Delphi, even though Delphi is generally the de facto standard. I was trying to explain that we did not do it differently simply because our way was the right one and Delphi's way the wrong one, or out of spite or so. But it appears that you interpreted my answer in exactly the opposite sense (that we won't change it out of spite).

Yup. Got that. It's just that I've heard it a few times before and was a bit confounded by the rational. No

Show quoted text 5 lines
The main problem with changing it now would obviously be that it would break backwards compatibility with existing code. It could still be done in Delphi mode onlu, of course, but changing the behaviour of a calling convention (which is normally an ABI issue) based on a language syntax mode feels... not right.

I don't believe this fix would cause any problems with existing code. The fix has been when using cdecl to declare const structures as pointers to structures. That is to say:

function nanosleep(RequestedTime: PTimeSpec; Remaining: PTimeSpec):
Integer; cdecl;

Which would operate just the same.

Thank you all for your courtesy. I understand the issue better now.

I'll look into how to help out with the compiler development soon and hopefully help improve FPC.

Reply by email

Eduardo Morras
you wrote 31 lines
Hi all. I am new to fpc and linux in general, though I do have a long time experience with Delphi. I was writing some code basic system (using the libc library) when I ran across the following problem .. some code: const libc = 'libc.so.6'; type TTimeSpec = record Sec: Cardinal; { Seconds } NSec: Cardinal; { Nanoseconds } end; PTimeSpec = ^TTimeSpec; function nanosleep(const RequestedTime: TTimeSpec; Remaining: PTimeSpec): Integer; cdecl; external libc; The problem with fpc and the above import is with the RequestedTime parameter, declared as a const record. In Delphi declaring a const record parameter cause the compiler to generate code to pass the record by reference (that is to say passing the address). In fpc, however this is not happening. My question is why. Why isn't fpc generating the code to pass a const record as a reference? I can find tons of WinAPI code where records are passed as const references by Delphi. I see this issue causing me some headaches as I port my Delphi code to run across platforms using fpc.

One question, why do you reimplement libc<->fpc wrapping lib? This function is in the BaseUnix unit as fpnanosleep.

HTH

----------------------------------------------
Useful Acronyms: GPL = Greedy Pengüin Licence

Reply by email

Jonas Maebe
to Jonas Maebe: I was merely answering your question why we do it differently than Delphi, even though…
Jonas Maebe wrote 5 lines
The main problem with changing it now would obviously be that it would break backwards compatibility with existing code. It could still be done in Delphi mode onlu, of course, but changing the behaviour of a calling convention (which is normally an ABI issue) based on a language syntax mode feels... not right.

FWIW, there was a similar problem with the Mac OS X interfaces: these were generated based on the calling convention used by MetroWerks Pascal, which passes all const record parameters (regardless of their size) always by reference, but which is otherwise identical to our cdecl. The solution there has been to simply add an "mwpascal" calling convention. We can always add a delphicdecl (or similar calling convention), and then you'd need only one define at the start of your code:

{$define cdecl:=delphicdecl}

Since most large projects already have a common include file for all sources, it shouldn't cause that much work. Also, to implement something like that you either need a detailed description of all the behaviours (which there does not appear to be for cdecl in case of Delphi), and/or an extensive test for all types (even with the description, you need the test to verify the implementation). That's a lot more work than the actual implementation work itself.

Jonas

Reply by email

Anthony Walter
to Eduardo Morras: One question, why do you reimplement libc<->fpc wrapping lib? This function is in the…
Eduardo Morras wrote
One question, why do you reimplement libc<->fpc wrapping lib? This function is in the BaseUnix unit as fpnanosleep.

I am redoing my game engine is which based on a simple concept. Bare bones code. The library is called bare actually and my unit names are prefixed with bare. Units are BareSystem, BareForms, BareGraphics, and BareOpenGL etc

Previously I'd already written this system with great success, but unfortunately I had tied platform specific code in places. I am trying to keep the toolkit as simple as possible and move the small runtime library and gui specific code into small interfacing units WindowsSystem, LinuxSystem linked from an IFDEF in BareSystem with an interface defining BareStubs unit both rely upon.

I have a small overview in this thread on the codegear forums (currently their security certificate has expired):

https://forums.codegear.com/thread.jspa?messageID=176408

An example screen from my engine is here:

http://imagebot.org/snapshops/cartoon.jpg

Jonas:

I noticed the bit you posted which looked like this:

{$define cdecl:=delphicdecl}

Does this mean I can redefine patterns as seen by FPC? If this is the case it might be possible to use those directives to make working with operator overloading between FPC and Delphi a bit less cumbersome.

Reply by email

Jonas Maebe
to Anthony Walter

Anthony Walter wrote on Mon, 16 Nov 2009:

Show quoted text 8 lines
Jonas: I noticed the bit you posted which looked like this: {$define cdecl:=delphicdecl} Does this mean I can redefine patterns as seen by FPC?

Yes. They are basically equivalent to C macro's, except that they do not support parameters. See
http://www.freepascal.org/docs-html/prog/progsu45.html (and the linked page) for more info.

Jonas

---------------------------------------------------------------- This message was sent using IMP, the Internet Messaging Program.

Reply by email

Jürgen Hestermann
to Michael Van Canneyt: Ego is not the problem. Time is, as Jonas pointed out. My observations were purely from a…
In general we try to be Delphi compatible as much as time and backward compatibility permits.

I hate it if bugs or illogical things are copied from Delphi. It may be the case that Delphi vanishes one day. Then we still would have all these bugs in FPC/Lazarus cast in stone forever. I think we should not slavish copy whatever Delphi does. Even if migration is a bit more work, the result of a cleaner and more logical code justifies it.

Reply by email

Anthony Walter
to Jürgen Hestermann
Jürgen Hestermann wrote 5 lines
I hate it if bugs or illogical things are copied from Delphi. It may be the case that Delphi vanishes one day. Then we still would have all these bugs in FPC/Lazarus cast in stone forever. I think we should not slavish copy whatever Delphi does. Even if migration is a bit more work, the result of a cleaner and more logical code justifies it.

I agree in principle, but for practical purposes I have a difficult time thinking of any glaring Delphi bugs strangeness.

Sure back in the Delphi 2.0 the automated section was a bad thing., but they got rid of it in the next version and gave us interface types instead (which are good).

I think Delphi should be using actual operators like + * and / instead of Add, Multiply, Divide, but then again I think the named results of FPC are stranger. What's wrong with using the type in the declaration and Result in the implementation?

Then there are the itterator thing, and generics ... I don't know enough about the syntax differences between FPC and Delphi to comment.

Point being, I haven't seen Delphi add too much that didn't make a some of sense (they might have flubbed generics and itterators).

Reply by email

Jonas Maebe
to Anthony Walter
Anthony Walter wrote
I think Delphi should be using actual operators like + * and / instead of Add, Multiply, Divide, but then again I think the named results of FPC are stranger. What's wrong with using the type in the declaration and Result in the implementation?

1) this feature was probably implemented before FPC had a Delphi/ ObjFpc mode and the associated result alias for the function result
2) even then, we'd still want to support this functionality in standard FPC mode anyway (which does not have this result alias)

For this reason, I think the Delphi operator naming decision is actually better than FPC's. Limiting them to classes is another matter.

Jonas

Reply by email

Marco van de Voort
to Jürgen Hestermann: I hate it if bugs or illogical things are copied from Delphi. It may be the case that…

In our previous episode, J�rgen Hestermann said:

Show quoted text 9 lines
> In > general we try to be Delphi compatible as much as time and > backward compatibility permits. I hate it if bugs or illogical things are copied from Delphi. It may be the case that Delphi vanishes one day. Then we still would have all these bugs in FPC/Lazarus cast in stone forever. I think we should not slavish copy whatever Delphi does. Even if migration is a bit more work, the result of a cleaner and more logical code justifies it.

I don't agree in general. It makes sharing code (not migration) very hard.

However in this case, there is much less installed base on Delphi, since most dlls simply use stdcall

Reply by email

Anthony Walter
to Jonas Maebe: 1) this feature was probably implemented before FPC had a Delphi/ ObjFpc mode and the…
Jonas Maebe wrote 5 lines
For this reason, I think the Delphi operator naming decision is actually better than FPC's. Limiting them to classes is another matter. Jonas

Jonas,

Delphi doesn't limit operator overloading to classes. You can also add overloading to in (addition to methods and inlining) records.

  TVec3 = record
    {$IFDEF D10_UP}
    function Cross(const V: TVec3): TVec3; inline;
    function Dot(const V: TVec3): Float; inline;
    procedure Normalize; inline;
    class operator Add(const A, B: TVec3): TVec3; inline;
    class operator Subtract(const A, B: TVec3): TVec3; inline;
    class operator Multiply(const A, B: TVec3): TVec3; inline;
    class operator Multiply(const A: TVec3; B: Float): TVec3; inline;
    class operator Divide(const A, B: TVec3): TVec3; inline;
    class operator Divide(const A: TVec3; B: Float): TVec3; inline;
    {$ENDIF}
    case Integer of
    0: (X, Y, Z: Float);
    1: (R, G, B: Float);
    2: (Red, Green, Blue: Float);
    3: (Heading, Pitch, Roll: Float);
    4: (Hue, Saturation, Lightness: Float);
    5: (V: array[0..2] of Float);
  end;
  PVec3 = ^TVec3;

Reply by email

Jonas Maebe
to Anthony Walter
Anthony Walter wrote 13 lines
On Mon, Nov 16, 2009 at 1:39 PM, Jonas Maebe < > wrote: > For this reason, I think the Delphi operator naming decision is > actually > better than FPC's. Limiting them to classes is another matter. > > > Jonas Jonas, Delphi doesn't limit operator overloading to classes. You can also add overloading to in (addition to methods and inlining) records.

I knew about the methods, but not about the operators, thanks. The "methods in records" is one thing I don't understand though, because TP-style objects without vutual methods are functionally identical, afaik.

Jonas

Reply by email