Recent

Author Topic: Definition C array to Pascal array  (Read 9243 times)

fpctuxe

  • Newbie
  • Posts: 4
Definition C array to Pascal array
« on: May 30, 2021, 05:54:25 pm »
Hello,

I’m porting a C library to pascal. In the c- header file I found a array definition. I have problems to translate to pascal. The structures are used to allocate a buffer and returned with  pdesc_list.

Example
C:
 
Code: C  [Select][+][-]
  1. struct desc {
  2.   unsigned int length;
  3.   unsigned int count;
  4. };
  5.  
  6. struct desc_list {
  7.   unsigned int num_desc;
  8.   struct desc descs[];          //here are the problem.
  9. };
  10. desc_list *pdesc_list;


Pascal:

Code: Pascal  [Select][+][-]
  1. desc = record
  2.   length: Cardinal;
  3.   count: Cardinal;
  4. end;
  5.  
  6. desc_list = record
  7.   num_desc: Cardinal
  8.   descs: array [] of desc;      //is not pascal conform.
  9. end;
  10. pdesc_list =^desc_list;
  11.  
  12. descs: array of desc;   //Is a Pointer to a array (dynamic array).
  13.  
  14. descs: array [0..1000000] of desc; //This works, but is not ideal.

My question: Gives a pascal declaration equivalent to C.

Thanks for your help.

[Edited to add code tags - please see How to use the Forum]
« Last Edit: May 31, 2021, 01:20:20 am by trev »

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Definition C array to Pascal array
« Reply #1 on: May 30, 2021, 06:22:32 pm »
if this is a GCC code with Zero-length array extension, then you might want to try this:
Code: Pascal  [Select][+][-]
  1. desc_list = record
  2.   num_desc: Cardinal
  3.   descs: array [0..0] of desc;     // remember to disable Range check when using desc_list
  4. end;
You can still access the array as following
Code: Pascal  [Select][+][-]
  1. var
  2.   l : desc_list;
  3.   i : integer;
  4. begin
  5.   i:=100;
  6.   l.descs[i].count
  7.  

but it would cause an error if range checks are on

fpctuxe

  • Newbie
  • Posts: 4
Re: Definition C array to Pascal array
« Reply #2 on: May 30, 2021, 07:30:08 pm »
Thanks, this is it.

Code: Pascal  [Select][+][-]
  1. var
  2.   l : desc_list;
  3.   i : integer;
  4. begin
  5.   i:=100;
  6. {$PUSH}{$WARN 4110 OFF}  
  7.   l.descs[i].count:= 12345
  8. {$POP}
  9.  

Is this the right way to disable range check?

fpctuxe

  • Newbie
  • Posts: 4
Re: Definition C array to Pascal array
« Reply #3 on: May 30, 2021, 08:10:57 pm »
This is not the right way.

fpctuxe

  • Newbie
  • Posts: 4
Re: Definition C array to Pascal array
« Reply #4 on: May 30, 2021, 08:14:25 pm »
This is it.
Code: Pascal  [Select][+][-]
  1. var
  2.   l : desc_list;
  3.   i : integer;
  4. begin
  5.   i:=100;
  6. {$PUSH}
  7. {$WARN 4110 OFF} {$RANGECHECKS OFF}  
  8.   l.descs[i].count:= 12345
  9. {$POP}
  10.  

or not?

440bx

  • Hero Member
  • *****
  • Posts: 3946
Re: Definition C array to Pascal array
« Reply #5 on: May 30, 2021, 08:17:36 pm »
or not?
Another option is to simply _not_ enabling range checks at all.  That way, there is no need to disable them.

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: Definition C array to Pascal array
« Reply #6 on: May 31, 2021, 12:00:55 am »
That  is an empty Array at the end of the tunnel.. Pascal does not have that and it can cause problems because the Record now becomes larger than it should if you use a [0..0] which gives you 1 element.

The C implementation does not give you any elements, it uses the first slot after the record/Struct.

Until the DEV decide to advance the compiler a little you will need to live with hacks.

Use a Blank Record at the end , give it a name and then type cast over it when using it.

Record

 Some fields;

EmptyArray :Record End;
End;

To use it.
either use the absolute key word to point an array to EmptyArray or type cast on the fly.
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: Definition C array to Pascal array
« Reply #7 on: May 31, 2021, 01:15:19 am »
here is a concept model of using a helper on the record to make life easier..
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$modeSwitch AdvancedRecords}
  5.  
  6. interface
  7.  
  8. uses
  9.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  10.  
  11. type
  12.  TDesc = Record
  13.     Length,Count:Cardinal;
  14.  end;
  15.  PDesc = ^TDesc;
  16.  TDesc_List = Record
  17.     num_desc:Cardinal;
  18.     Descs:Record End;
  19.  end;
  20. TDisc_ListHelper = Record Helper for TDesc_List
  21.  Procedure SetDesc(index:Integer;aDesc:TDesc);inline;
  22.  Function GetDesc(Index:Integer):TDesc;inline;
  23. end;
  24.  
  25.   { TForm1 }
  26.  
  27.   TForm1 = class(TForm)
  28.     Button1: TButton;
  29.     procedure Button1Click(Sender: TObject);
  30.   private
  31.  
  32.   public
  33.  
  34.   end;
  35.  
  36. var
  37.   Form1: TForm1;
  38.  
  39. implementation
  40.  
  41. {$R *.lfm}
  42. Procedure TDisc_ListHelper.SetDesc(index:Integer;ADesc:TDesc);
  43. begin
  44.   PDesc(@Descs)[Index]:= ADesc;
  45. end;
  46. Function TDisc_ListHelper.GetDesc(Index:Integer):TDesc;
  47. Begin
  48.  Result := PDesc(@Descs)[Index];
  49. End;
  50. { TForm1 }
  51.  
  52. procedure TForm1.Button1Click(Sender: TObject);{A dummy test }
  53. var
  54.   A:TDesc_List;
  55. begin
  56.   A.num_desc :=-1;
  57.   Caption := A.GetDesc(-1).Count.Tostring;
  58. end;
  59.  
  60. end.
  61.  

all of this wouldn't be needed if an empty array could be applied at the end..  :(
The only true wisdom is knowing you know nothing

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Definition C array to Pascal array
« Reply #8 on: May 31, 2021, 04:41:49 am »
This is it.
..
or not?
yes using {$RANGECHECKS OFF} is the right way

...all of this wouldn't be needed if an empty array could be applied at the end..  :(
the feature is not even a part of the official C-standard.
why would it be needed for the implementation in pascal?

One could do an implementation like this:
Code: Pascal  [Select][+][-]
  1. desc = record
  2.   length : Cardinal;
  3.   count  : Cardinal;
  4. end;
  5.  
  6. desc_list = record
  7.   num_desc : Cardinal;
  8.   descs    : array [0..0] of desc;     // remember to disable Range check when using desc_list
  9. end;
  10.  
  11. tdescarray = array [word] of desc; // even "Integer" would work for 64-bit mode
  12. pdescarray = ^tdescarray;
  13.  
  14. desc_listPtr = record
  15.   num_desc : Cardinal;
  16.   descs    : pdescarray;
  17. end;
  18.  
  19. procedure InitDescList(const inp: desc_list; out pt: desc_listPtr )
  20. begin
  21.   pt.numdesc := inp.numdesc;
  22.   pt.descs := @inp.descs;
  23. end;

and dealing with "pt.desc" would allow to avoid RANGECHECKS off (assuming num_desc is less than 65535... which usually it's less than that)

Another approach is similar to suggested originally:
Code: Pascal  [Select][+][-]
  1. desc_list = record
  2.   num_desc : Cardinal;
  3.   descs    : array [word] of desc;     // array[byte]?
  4. end;
  5.  

The actually approach on how to deal with the C-specific type should be chosen based on several things:
* is the type only returned from the library (and doesn't need be built by the program)
* what the maximum num_desc is "logically" expected/possible. (could a type declared with a certain amount of entries in the array)
* is the data returned from desc_list will be copied over to some other storage within the program. (if yes, then dealing with RANGECHECKS off one time, will solve the problem)
« Last Edit: May 31, 2021, 04:56:20 am by skalogryz »

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: Definition C array to Pascal array
« Reply #9 on: May 31, 2021, 12:43:18 pm »
I see this is going to turn into a long discussion of antics so I will keep it short as this will most likely be the last post I place here.

C language allows empty Arrays at the end of a struct or actually in the middle too depending on the code structure.

This tactic has been used for years and its even in the C++ world.

The idea Is to place a TAG (Address) marker of an array that would appear after the struct so that TAG, that being the name of the empty array,  actually points outside of the struct just following its declaration.

 The closes fpc has to offer is an Empty Record at the end for which its TAG will be pointing to the start of any following memory.

 if the coder does not mind using a type cast on the fly then a type can be used to enclose this TAG..

 
Code: Pascal  [Select][+][-]
  1.  Type
  2.     TMyCast = Array[0..0] of TDesc;
  3.  

 Then in theory

Code: Pascal  [Select][+][-]
  1. TMyCast(MyRecordInstance.TheRecordTag)[?] :=?
  2.  

 Using a variable for the index at runtime should avoid compiler stoppage..

Have a good day and may the bugs be many. :o
The only true wisdom is knowing you know nothing

Kays

  • Hero Member
  • *****
  • Posts: 569
  • Whasup!?
    • KaiBurghardt.de
Re: Definition C array to Pascal array
« Reply #10 on: May 31, 2021, 10:30:13 pm »
or not?
Another option is to simply _not_ enabling range checks at all.  That way, there is no need to disable them.
Yes, but it is in fact good practice to surround the specific LOC with a {$push}{$R-} and {$pop} if you are relying on that behavior. During development it’s a good idea to compile and use a program compiled with ‑dDEBUG [cf. /etc/fpc.cfg], and even if you don’t the {$rangeChecks off} still serves documentation purposes.
Yours Sincerely
Kai Burghardt

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Definition C array to Pascal array
« Reply #11 on: May 31, 2021, 10:50:09 pm »
C language allows empty Arrays at the end of a struct or actually in the middle too depending on the code structure.
...
The idea Is to place a TAG (Address) marker of an array that would appear after the struct so that TAG, that being the name of the empty array,  actually points outside of the struct just following its declaration.

Thanks for that Jamie, succinct and useful.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Definition C array to Pascal array
« Reply #12 on: May 31, 2021, 10:53:23 pm »
Another option is to simply _not_ enabling range checks at all.  That way, there is no need to disable them.
Yes, but it is in fact good practice to surround the specific LOC with a {$push}{$R-} and {$pop} if you are relying on that behavior. During development it’s a good idea to compile and use a program compiled with ‑dDEBUG [cf. /etc/fpc.cfg], and even if you don’t the {$rangeChecks off} still serves documentation purposes.

I agree. Unless a body of code has been /proven/- and I'm using the word in the strict mathematical sense with everything that implies- to be incapable of an out-of-range operation, I have a lot of difficulty envisaging a situation where simply accepting an erroneous result can be considered even remotely acceptable.

MarkMLl

MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

440bx

  • Hero Member
  • *****
  • Posts: 3946
Re: Definition C array to Pascal array
« Reply #13 on: June 01, 2021, 12:18:11 am »
or not?
Another option is to simply _not_ enabling range checks at all.  That way, there is no need to disable them.
Yes, but it is in fact good practice to surround the specific LOC with a {$push}{$R-} and {$pop} if you are relying on that behavior. During development it’s a good idea to compile and use a program compiled with ‑dDEBUG [cf. /etc/fpc.cfg], and even if you don’t the {$rangeChecks off} still serves documentation purposes.
I can agree that having {$rangeChecks off} serves documentation purposes. 

That said, a program should _not_ depend on range checking to operate correctly.  The other problem with enabling range checks is that, the final product will usually not be shipped with range checks enabled, which in turn means that the programmer is not gaining experience with code that will be part of the final product. 

It's important and very useful to keep the software being developed as close as possible to the version that will be shipped.  This avoids "bad surprises" after the software is shipped.

range checks should only be enabled when a problem is found during development and range checking may contribute to determining the cause of the problem.  The rest of the time, it should be disabled (as it will be in the final product.)
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Definition C array to Pascal array
« Reply #14 on: June 01, 2021, 09:04:14 am »
range checks should only be enabled when a problem is found during development and range checking may contribute to determining the cause of the problem.  The rest of the time, it should be disabled (as it will be in the final product.)

The point was about code that only works correctly with range checking disabled. This should be guarded correctly like mentioned above so that if one decides to enable range checking (either because one develops with them enabled or because one has a problem that one hopes to find with range checks) then one doesn't have to hunt false positives.

 

TinyPortal © 2005-2018