Sign in Join

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

Mailing lists / fpc-pascal / 2023-01

Why in {$mode delphi} it works and in {$mode objfpc} it doesn't?

8 messages · 4 people ·

Reply by email Subscribe to this list Your subscription

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

Giuliano Colla

I stumbled into a problem I don't understand.

I'm developing a little program for an ftp client. In order to connect to the site I need the site address from the site name, and the libc gethostbyname() provides the required information.

gethostbyname returns a PHostEnt type which is declared as:

Show quoted text 12 lines
THostEnt = packed record     h_name: PChar;                  { Official name of host. }     h_aliases: PPChar;              { Alias list.  }     h_addrtype: Integer;            { Host address type.  }     h_length: socklen_t;            { Length of address.  }     case Byte of       0: (h_addr_list: PPChar);     { List of addresses from name server.  }       1: (h_addr: PPChar);          { Address, for backward compatibility.  }   end;   PHostEnt = ^THostEnt;

Actually the chars h_addr points to are /hlength/ bytes to be interpreted as an /in_addr/

In order to recover h_addr I have a line which works perfectly in Delphi mode (inherited from an old Kylix app):

Addr := Pin_addr(HostEnt.h_addr^);

I believed that in objfpc mode it was sufficient to change it in

Addr := @(Pin_addr(HostEnt.h_addr^));

or in

Addr := Pin_addr(@HostEnt.h_addr^);

but such is not the case. In both cases it flags the line with the same error, i.e.:

Error: illegal qualifier
Hint: may be pointer dereference is missing
Fatal: Syntax error, ")" expected but "identifier H_ADDR" found

What I'm missing? How should i write that line of code to make it work in objfpc mode?

Thanks,

Giuliano

Reply by email

Michael Van Canneyt
to Giuliano Colla
Giuliano Colla wrote 33 lines
I stumbled into a problem I don't understand. I'm developing a little program for an ftp client. In order to connect to the site I need the site address from the site name, and the libc gethostbyname() provides the required information. gethostbyname returns a PHostEnt type which is declared as: > THostEnt = packed record >     h_name: PChar;                  { Official name of host. } >     h_aliases: PPChar;              { Alias list.  } >     h_addrtype: Integer;            { Host address type.  } >     h_length: socklen_t;            { Length of address.  } >     case Byte of >       0: (h_addr_list: PPChar);     { List of addresses from name server.  > } >       1: (h_addr: PPChar);          { Address, for backward compatibility.  > } >   end; >   PHostEnt = ^THostEnt; Actually the chars h_addr points to are /hlength/ bytes to be interpreted as an /in_addr/ In order to recover h_addr I have a line which works perfectly in Delphi mode (inherited from an old Kylix app): > Addr := Pin_addr(HostEnt.h_addr^); I believed that in objfpc mode it was sufficient to change it in > Addr := @(Pin_addr(HostEnt.h_addr^)); or in > Addr := Pin_addr(@HostEnt.h_addr^);

Should that not simply be

Addr := Pin_addr(HostEnt.h_addr^)

(if addr is a pointer)

or

addr:=Pin_addr(HostEnt.h_addr^)^

if Addr is an in_addr record ?

Michael.

Reply by email

Giuliano Colla
to Michael Van Canneyt

Il 16/01/23 20:32, Michael Van Canneyt ha scritto:

Show quoted text 18 lines
On Mon, 16 Jan 2023, Giuliano Colla via fpc-pascal wrote: > .....I stumbled into a problem I don't understand. Should that not simply be Addr := Pin_addr(HostEnt.h_addr^) (if addr is a pointer) or addr:=Pin_addr(HostEnt.h_addr^)^ if Addr is an in_addr record ? Michael.

No chance. Addr is a pointer (of type Pin_addr)

but

Addr := Pin_addr(HostEnt.h_addr^)

works only if mode is Delphi. In objfpc it raises exactly the same error.

A little bit weird, isn't it?

Giuliano

Reply by email

Marco van de Voort
to Giuliano Colla
Giuliano Colla wrote 11 lines
No chance. Addr is a pointer (of type Pin_addr) but Addr := Pin_addr(HostEnt.h_addr^) works only if mode is Delphi. In objfpc it raises exactly the same error. A little bit weird, isn't it?

It depends. It assumes .h_addr is compatible with pointer.  Since Free Pascal is more portable, that might be a platform dependent assumption.

Reply by email

Mattias Gaertner
to Giuliano Colla: I stumbled into a problem I don't understand. I'm developing a little program for an ftp…
Show quoted text 22 lines
I stumbled into a problem I don't understand. I'm developing a little program for an ftp client. In order to connect to the site I need the site address from the site name, and the libc gethostbyname() provides the required information. gethostbyname returns a PHostEnt type which is declared as: > THostEnt = packed record >     h_name: PChar;                  { Official name of host. } >     h_aliases: PPChar;              { Alias list.  } >     h_addrtype: Integer;            { Host address type.  } >     h_length: socklen_t;            { Length of address.  } >     case Byte of >       0: (h_addr_list: PPChar);     { List of addresses from name > server.  } >       1: (h_addr: PPChar);          { Address, for backward > compatibility.  } >   end; >   PHostEnt = ^THostEnt; Actually the chars h_addr points to are /hlength/ bytes to be interpreted as an /in_addr/

Then either

Addr := Pin_addr(HostEnt.h_addr)^;

or

Addr := Pin_addr(HostEnt.h_addr^)^;

Mattias

Reply by email

Mattias Gaertner
to Mattias Gaertner
Show quoted text 10 lines
On Mon, 16 Jan 2023 19:50:34 +0100 Giuliano Colla via fpc-pascal wrote: > I stumbled into a problem I don't understand. > > I'm developing a little program for an ftp client. In order to > connect to the site I need the site address from the site name, and > the libc gethostbyname() provides the required information. > > gethostbyname returns a PHostEnt type which is declared as:

Btw, gethostbyname is obsolete. Applications should use getaddrinfo, getnameinfo, and gai_strerror instead.

Show quoted text 15 lines
> > THostEnt = packed record > >     h_name: PChar;                  { Official name of host. } > >     h_aliases: PPChar;              { Alias list.  } > >     h_addrtype: Integer;            { Host address type.  } > >     h_length: socklen_t;            { Length of address.  } > >     case Byte of > >       0: (h_addr_list: PPChar);     { List of addresses from name > > server.  } > >       1: (h_addr: PPChar);          { Address, for backward > > compatibility.  } > >   end; > >   PHostEnt = ^THostEnt; > Actually the chars h_addr points to are /hlength/ bytes to be > interpreted as an /in_addr/ [...]

Ah, I just saw gethostbyname returns a PHostEnt and Addr is Pin_addr.

Then for the first address:
  Addr := Pin_addr(HostEnt^.h_addr[0]);

Mattias

Reply by email

Giuliano Colla
to Marco van de Voort: It depends. It assumes .h_addr is compatible with pointer.  Since Free Pascal is more…

Il 16/01/23 20:58, Marco van de Voort via fpc-pascal ha scritto:

Show quoted text 17 lines
On 16-1-2023 20:56, Giuliano Colla via fpc-pascal wrote: > > No chance. Addr is a pointer (of type Pin_addr) > > but > > Addr := Pin_addr(HostEnt.h_addr^) > > works only if mode is Delphi. In objfpc it raises exactly the same > error. > > A little bit weird, isn't it? > It depends. It assumes .h_addr is compatible with pointer.  Since Free Pascal is more portable, that might be a platform dependent assumption.

I fail to grasp the different assumptions that the compiler makes on objfpc mode. If the typecast tells that the two types are compatible (and they are, because they're both pointers and also of the same type) it should write the one to the other without making any fuss! But I can live with it! The horrible mess they've done with gethostbyname, and the chars which are actually bytes is not so frequent, luckily! That's what happens when you don't have the "based" construct, which makes very easy to deal with those situations. Different structures can be based on the same pointer, and one "type" field, common to all structures, makes you pick up the right one.

Giuliano

Giuliano

Reply by email

Giuliano Colla
to Mattias Gaertner: On Mon, 16 Jan 2023 22:12:52 +0100 Btw, gethostbyname is obsolete. Applications should…

Il 16/01/23 22:23, Mattias Gaertner via fpc-pascal ha scritto:

Show quoted text 16 lines
On Mon, 16 Jan 2023 22:12:52 +0100 Mattias Gaertner via fpc-pascal wrote: > On Mon, 16 Jan 2023 19:50:34 +0100 > Giuliano Colla via fpc-pascal wrote: > >> I stumbled into a problem I don't understand. >> >> I'm developing a little program for an ftp client. In order to >> connect to the site I need the site address from the site name, and >> the libc gethostbyname() provides the required information. >> >> gethostbyname returns a PHostEnt type which is declared as: Btw, gethostbyname is obsolete. Applications should use getaddrinfo, getnameinfo, and gai_strerror instead.

I know that it's obsolete. It's not reentrant and it is ugly. But I'm pretty sure that it will survive for a long time to come, because it provides you a check on a name *before* creating a socket. If the name is wrong (a typo, e.g.) you don't need to get rid of an useless socket, as it would happen with getaddrinfo and getnameinfo.

Show quoted text 6 lines
>>> [...] Ah, I just saw gethostbyname returns a PHostEnt and Addr is Pin_addr. Then for the first address: Addr := Pin_addr(HostEnt^.h_addr[0]);

IT WORKS!

But for me it's a bit obscure why in Delphi mode the right syntax is

HostEnt.h_addr^

and in objfpc

HostEnt.h^.h_addr[0]

I can understand the first caret (Delphi puts it there implicitly) but not the rest.

However thanks a lot. If gethostbyname can be a little obsolete, Delphi mode for me is much more obsolete and deprecated!

Giuliano

Reply by email