Recent

Author Topic: Pascal const Record array stored identically as a C const struct array?  (Read 9169 times)

TCH

  • Full Member
  • ***
  • Posts: 200
I have the following C structs:
Code: C  [Select][+][-]
  1. typedef struct
  2. {
  3.         char *a;
  4.         void *b;
  5. } entry;
  6.  
  7. typedef struct
  8. {
  9.         int size;
  10.         entry *entries;
  11. } table;
So when i say
Code: C  [Select][+][-]
  1. t->entries[0]
it will directly point to the entry, with the two pointers (*a and *b). However, when i try to convert this to Pascal:
Code: Pascal  [Select][+][-]
  1. table_entry = record
  2.         a: AnsiString;
  3.         b: Pointer;
  4. end;
  5. atable_entry = array of table_entry;
  6. patable_entry = ^atable_entry;
  7.  
  8. table = record
  9.         size: integer;
  10.         entries: patable_entry;
  11. end;
  12. ptable = ^table;
and i try to pass a list from a Pascal executable to a C library, then it does not work, because
Code: C  [Select][+][-]
  1. t->entries[0]
will not point to the item with the two pointers directly, but to a pointer to the item. So, this list in C
Code: C  [Select][+][-]
  1. table_entry t_table_entries[] =
  2. {
  3.         {"a", (void *)&a},
  4.         {"b", (void *)&b},
  5.         {"c", (void *)&c},
  6.         {"d", (void *)&d},
  7. };
  8. table t_table =
  9. {
  10.         sizeof(t_table_entries) / sizeof(table_entry),
  11.         &t_table_entries[0],
  12. };
can be passed to the C library, but this very same list in Pascal
Code: Pascal  [Select][+][-]
  1. t_table_entries: atable_entry =
  2. (
  3.         (symbol: 'a'; funcptr: @a),
  4.         (symbol: 'b'; funcptr: @b),
  5.         (symbol: 'c'; funcptr: @c),
  6.         (symbol: 'd'; funcptr: @d),
  7. );
  8. t_table: table =
  9. (
  10.         size: 4;
  11.         entries: @t_table_entries;
  12. );
cannot. What i am doing wrong? Is it possible to store an array of Record the same way as it is stored in C; the array directly containing the records and not pointers to each one? (I am aware that i could allocate memory directly for it and copy the items into it, but what i need is the identical initialization of the list from const or var.)

Zvoni

  • Hero Member
  • *****
  • Posts: 2300
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #1 on: October 15, 2021, 01:09:18 pm »
I would have expected something like this
Code: Pascal  [Select][+][-]
  1. Type
  2.   TEntry = Record
  3.       a:PChar;
  4.       b:Pointer;
  5.   End;
  6.   PEntry = ^TEntry;
  7.  
  8.   TTable = Record
  9.       Size:Integer;
  10.       Entries:PEntry;
  11.   End;
  12.  
  13. Var
  14.   arrEntries:Array[0..3] Of TEntry; //Or dynamic array
  15.  
  16.  
  17.  
« Last Edit: October 15, 2021, 01:26:21 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

alpine

  • Hero Member
  • *****
  • Posts: 1032
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #2 on: October 15, 2021, 01:09:55 pm »
You should make difference between:
Code: [Select]
atable_entry = array of table_entry; and
Code: [Select]
atable_entry = array [0..n-1] of table_entry;The first array is known as dynamic.

P.S. Also AnsiStrings are not the same as C asciiz strings, use PChar instead.
« Last Edit: October 15, 2021, 01:12:59 pm by y.ivanov »
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

Zvoni

  • Hero Member
  • *****
  • Posts: 2300
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #3 on: October 15, 2021, 01:36:12 pm »
Forgot:
This is using "native" Pascal-types.
When interfacing with a c-library the usage of the ctypes-unit (and its types) is recommended.

And i can never remember, which Packrecords-directive to use
{$PACKRECORDS C} ?
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

TCH

  • Full Member
  • ***
  • Posts: 200
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #4 on: October 15, 2021, 01:38:30 pm »
Okay guys, thank you all. This setup works:
Code: Pascal  [Select][+][-]
  1. table_entry = record
  2.         symbol: PChar;
  3.         funcptr: Pointer;
  4. end;
  5. ptable_entry = ^table_entry;
  6.  
  7. table = record
  8.         size: integer;
  9.         entries: ptable_entry;
  10. end;
  11. ptable = ^table;
Code: Pascal  [Select][+][-]
  1. t_table_entries: array[0..3] of table_entry =
  2. (
  3.         (symbol: 'a'; funcptr: @a),
  4.         (symbol: 'b'; funcptr: @b),
  5.         (symbol: 'c'; funcptr: @c),
  6.         (symbol: 'd'; funcptr: @d)
  7. );
  8. t_table: table =
  9. (
  10.         size: length(t_table_entries);
  11.         entries: @t_table_entries[0];
  12. );
Is it possible to omit the [0..3] part somehow? Or in Pascal i have to pre-declare the size of a constant static array, the compiler cannot calculate the size by the entries?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11352
  • FPC developer.
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #5 on: October 15, 2021, 02:03:37 pm »
Is it possible to omit the [0..3] part somehow? Or in Pascal i have to pre-declare the size of a constant static array, the compiler cannot calculate the size by the entries?

Add {$pointermath on}  after your {$mode } line.

Then use a pointer to the table entry. ( entries: Ptable_entry;    with ptable_entry = ^table_entry; ) and overindex it like in C

TCH

  • Full Member
  • ***
  • Posts: 200
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #6 on: October 15, 2021, 03:00:59 pm »
Then use a pointer to the table entry. ( entries: Ptable_entry;    with ptable_entry = ^table_entry; )
It is already that way.
and overindex it like in C
I don't understand this. I did not overindex anything in C. In the C version, the number of items was calculated by
Code: C  [Select][+][-]
  1. sizeof(t_table_entries) / sizeof(table_entry)

Kays

  • Hero Member
  • *****
  • Posts: 569
  • Whasup!?
    • KaiBurghardt.de
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #7 on: October 15, 2021, 03:08:06 pm »
Code: Pascal  [Select][+][-]
  1. table = record
  2.         size: integer;
  3.         entries: ptable_entry;
  4. end;
You should really use CInt: In FPC integer depends on the used compiler compatibility mode.
Yours Sincerely
Kai Burghardt

TCH

  • Full Member
  • ***
  • Posts: 200
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #8 on: October 15, 2021, 03:36:00 pm »
Got it, thanks.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11352
  • FPC developer.
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #9 on: October 15, 2021, 03:49:18 pm »
and overindex it like in C
I don't understand this. I did not overindex anything in C. In the C version, the number of items was calculated by
Code: C  [Select][+][-]
  1. sizeof(t_table_entries) / sizeof(table_entry)

The overindexing is if you access t_table_entries via the  table.entries pointer. That pointer is ^table_index; so talbe.entries[3] is overindexing (as in indexing more than declared, since you declare it as pointing to one item, but treat it as an array where you acccess the fourth item ). Note that overindexing is not entirely the same as out-of-bounds access. It is merely accessing more items that you declare, even if you ensure by other means that they are there.

TCH

  • Full Member
  • ***
  • Posts: 200
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #10 on: October 15, 2021, 05:29:36 pm »
I know what is overindexing, but why should i do that here? I have the code
Code: Pascal  [Select][+][-]
  1. t_table_entries: array[0..3] of table_entry =
  2. (
  3.         (symbol: 'a'; funcptr: @a),
  4.         (symbol: 'b'; funcptr: @b),
  5.         (symbol: 'c'; funcptr: @c),
  6.         (symbol: 'd'; funcptr: @d)
  7. );
  8.  
  9. t_table: table =
  10. (
  11.         size: length(t_table_entries);
  12.         entries: @t_table_entries[0];
  13. );
and i would like to avoid specifiying the boundaries of the array at the declaration ([0..3]), because if i add more elements, then i have to re-specify that too each time. (I know, not a big deal, i can live with it, but would be better.)
So, i don't understand how overindexing comes into the picture here...

ASerge

  • Hero Member
  • *****
  • Posts: 2212
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #11 on: October 16, 2021, 10:31:31 am »
Is it possible to omit the [0..3] part somehow? Or in Pascal i have to pre-declare the size of a constant static array, the compiler cannot calculate the size by the entries?
If initialize during execution:
Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2.  
  3. type
  4.   TEntry = record
  5.     A: PAnsiChar;
  6.     B: Pointer;
  7.   end;
  8.  
  9.   TTable = record
  10.     Count: Int32;
  11.     Entries: array of TEntry;
  12.   end;
  13.  
  14. const
  15.   CEntry1: TEntry = (A: 'a'; B: nil);
  16.   CEntry2: TEntry = (A: 'b'; B: nil);
  17.   CEntry3: TEntry = (A: 'c'; B: nil);
  18.   CEntry4: TEntry = (A: 'd'; B: nil);
  19. var
  20.   Tbl: TTable;
  21. begin
  22.   Tbl.Entries := [CEntry1, CEntry2, CEntry3, CEntry4];
  23.   Tbl.Count := Length(Tbl.Entries);
  24. end.

TCH

  • Full Member
  • ***
  • Posts: 200
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #12 on: October 17, 2021, 11:38:17 am »
This will result in a dynamical array too:
Code: Pascal  [Select][+][-]
  1. WriteLn(Char(Pointer(Pointer(@(Tbl.Entries[0]))^)^));
Code: [Select]
a

Thaddy

  • Hero Member
  • *****
  • Posts: 14166
  • Probably until I exterminate Putin.
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #13 on: October 17, 2021, 12:49:24 pm »
yes, but that is not complete.
An example that fits the C syntax, and that can be nested too:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2. type
  3.   TMyrec = packed record
  4.    a:integer;
  5.    b:single;
  6.   end;
  7.   TMyRecArray = packed array[0..2] of TMyRec;
  8. const  
  9.   constantarr:TMyRecArray = (
  10.   (a:1;b:1.0),
  11.   (a:2;b:2.2),
  12.   (a:3;b:3.3)
  13.   );
  14. var
  15.   rec:TMyRec;
  16. begin
  17.   for rec in constantarr do
  18.     writeln(rec.a, rec.b);
  19. end.
I used that a lot for really fixed array structures.
[edit:] I just saw ASerge gave about the same answer. And is just as correct.
That pointer rubbish is not necessary at all.

Point is you just have to know the proper Pascal syntax to do it like in C. Focus on pointers is not necessary at all..
« Last Edit: October 17, 2021, 01:22:17 pm by Thaddy »
Specialize a type, not a var.

Zvoni

  • Hero Member
  • *****
  • Posts: 2300
Re: Pascal const Record array stored identically as a C const struct array?
« Reply #14 on: October 17, 2021, 03:10:34 pm »
Thaddy, are you sure?
OP stated in his first post, that he wants to pass those records to a c-lib
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

 

TinyPortal © 2005-2018