Recent

Author Topic: Imported C Structure is not mapped correctly  (Read 1095 times)

domibay_hugo

  • New Member
  • *
  • Posts: 37
  • Site Reliabilty / DevOps Engineer at Domibay S.L.
    • GitHub Profile
Imported C Structure is not mapped correctly
« on: January 04, 2021, 04:30:28 pm »
I'm developing an Application that interacts with an External Shared Library over a C Language Structure:
Code: C  [Select][+][-]
  1. #define MAX_RESULT 128
  2.  
  3. typedef struct FooResult {
  4.   uint32_t iversion;
  5.   int8_t iresultcount;
  6.   int8_t ierrorcode;
  7.   int64_t arrresult[MAX_RESULT];
  8. } FooResult;
  9.  

So I created this Pascal Structure:
Code: Pascal  [Select][+][-]
  1. const
  2.   MAX_RESULT = 128;
  3.  
  4. type
  5.   PResultArray = ^TResultArray;
  6.   TResultArray = array[0..(MAX_RESULT - 1)] of Int64;
  7.  
  8.   PFooResult = ^TFooResult;
  9.   TFooResult = packed record
  10.     iversion: cuint32;
  11.     iresultcount: cint8;
  12.     ierrorcode: cint8;
  13.     arrresult: TResultArray;
  14.   end;
  15.  

The issue that I'm observing is that the Array TFooResult.arrresult cannot be accessed correctly.
But when reading the Array TResultArray FreePascal shows the values correctly.

The Library Code is:
Code: C  [Select][+][-]
  1. #include <stdint.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4.  
  5.  
  6.  
  7. #define MAX_RESULT 128
  8.  
  9.  
  10. typedef struct FooResult {
  11.   uint32_t iversion;
  12.   int8_t iresultcount;
  13.   int8_t ierrorcode;
  14.   int64_t arrresult[MAX_RESULT];
  15. } FooResult;
  16.  
  17.  
  18. /* fooutils.h */
  19.  
  20. extern FooResult* foo_get_result();
  21. extern void foo_build_result(FooResult*);
  22. extern const int64_t* foo_get_result_array(const FooResult*);
  23. extern void foo_result_debug(const FooResult*);
  24. extern void foo_result_free(FooResult*);
  25.  
  26.  
  27.  
  28.  
  29. FooResult* foo_get_result()
  30. {
  31.         FooResult* pfooresult = (FooResult*)malloc(sizeof(FooResult));
  32.         int irs;
  33.  
  34.  
  35.         pfooresult->iversion = 0;
  36.         pfooresult->iresultcount = -1;
  37.         pfooresult->ierrorcode = 0;
  38.  
  39.         for(irs = 0; irs < MAX_RESULT; irs++)
  40.         {
  41.                 pfooresult->arrresult[irs] = -1;
  42.         }
  43.  
  44.  
  45.         return pfooresult;
  46. }
  47.  
  48. void foo_build_result(FooResult* pfooresult)
  49. {
  50.         if(pfooresult != NULL)
  51.         {
  52.                 pfooresult->iversion += 1;
  53.                 pfooresult->ierrorcode = 0;
  54.  
  55.                 if(pfooresult->iresultcount <= 127)
  56.             {
  57.                 if(pfooresult->iresultcount != -1)
  58.                 {
  59.                         pfooresult->arrresult[pfooresult->iresultcount] = pfooresult->iversion;
  60.  
  61.                         pfooresult->iresultcount += 1;
  62.                 } else {
  63.                         pfooresult->arrresult[0] = pfooresult->iversion;
  64.  
  65.                   pfooresult->iresultcount = 1;
  66.                 }  //if frs.iresultcount != -1
  67.               } else {
  68.                   pfooresult->ierrorcode = 4;
  69.               }  //if(pfooresult->iresultcount <= 127)
  70.         }  //if(pfooresult != Null)
  71. }
  72.  
  73. const int64_t* foo_get_result_array(const FooResult* pfooresult)
  74. {
  75.         if(pfooresult != NULL)
  76.         {
  77.                 return pfooresult->arrresult;
  78.         }
  79.         else
  80.         {
  81.                 return NULL;
  82.         }
  83. }
  84.  
  85. void foo_result_debug(const FooResult* pfooresult)
  86. {
  87.         if(pfooresult != NULL)
  88.         {
  89.                 int irs;
  90.  
  91.  
  92.                 printf("FooResult* Debug: '*FooResult { iversion: %d, iresultcount: %d, ierrorcode: %d"
  93.                                 , pfooresult->iversion, pfooresult->iresultcount, pfooresult->ierrorcode);
  94.                 printf(", arrresult: [");
  95.  
  96.                 for(irs = 0; irs < MAX_RESULT; irs++)
  97.                 {
  98.                         if(irs > 0) { printf(", "); }
  99.  
  100.                         printf("%d", (int)pfooresult->arrresult[irs]);
  101.                 }
  102.  
  103.                 printf("] }'\n");
  104.         }
  105.         else  //FooResult is not set
  106.         {
  107.                 printf("FooResult Debug: 'NULL'\n");
  108.         }       //if(pfooresult != Null)
  109.  
  110. }
  111.  
  112. void foo_result_free(FooResult* pfooresult)
  113. {
  114.         if(pfooresult != NULL)
  115.         {
  116.                 free(pfooresult);
  117.         }
  118.  
  119. }
  120.  

the C Language Host Application is this:
Code: C  [Select][+][-]
  1. #include <stdint.h>
  2. #include <stdio.h>
  3.  
  4.  
  5. #define MAX_RESULT 128
  6.  
  7.  
  8. typedef struct FooResult {
  9.   uint32_t iversion;
  10.   int8_t iresultcount;
  11.   int8_t ierrorcode;
  12.   int64_t arrresult[MAX_RESULT];
  13. } FooResult;
  14.  
  15.  
  16. /* foo-utils.h */
  17.  
  18. extern FooResult* foo_get_result();
  19. extern void foo_build_result(const FooResult*);
  20. extern const int64_t* foo_get_result_array(const FooResult*);
  21. extern void foo_result_debug(const FooResult*);
  22. extern void foo_result_free(FooResult*);
  23.  
  24.  
  25.  
  26.  
  27. int main ()
  28. {
  29.         FooResult* pfoors;
  30.         const uint64_t* parrrs;
  31.     int irs, igtcnt;
  32.  
  33.     printf("FooResult: building ...\n");
  34.  
  35.     pfoors = foo_get_result();
  36.  
  37.     if(pfoors != NULL)
  38.     {
  39.         printf("FooResult: built.\n");
  40.  
  41.         printf("FooResult - Debug 0:\n");
  42.  
  43.         foo_result_debug(pfoors);
  44.  
  45.         printf("FooResult - Content:\n");
  46.  
  47.         printf("FooResult - Code: [%d]\n", pfoors->ierrorcode);
  48.         printf("FooResult: Version '%d'\n", pfoors->iversion);
  49.         printf("FooResult: (Count: '%d / %d'):\n", pfoors->iresultcount, MAX_RESULT);
  50.  
  51.         for(irs = 0; irs < pfoors->iresultcount; irs++)
  52.         {
  53.           printf("FooResult: Result[%d]: '%d'\n", irs, pfoors->arrresult[irs]);
  54.         }
  55.  
  56.       printf("FooResult: 3 Results filling ...\n");
  57.  
  58.       printf("FooResult: Result 1 filling ...\n");
  59.  
  60.       foo_build_result(pfoors);
  61.  
  62.       printf("FooResult - Debug 1:\n");
  63.  
  64.       foo_result_debug(pfoors);
  65.  
  66.       printf("FooResult: Result 2 filling ...\n");
  67.  
  68.       foo_build_result(pfoors);
  69.  
  70.       printf("FooResult - Debug 2:\n");
  71.  
  72.       foo_result_debug(pfoors);
  73.  
  74.       printf("FooResult: Result 3 filling ...\n");
  75.  
  76.       foo_build_result(pfoors);
  77.  
  78.       printf("FooResult - Debug 3:\n");
  79.  
  80.       foo_result_debug(pfoors);
  81.  
  82.       printf("FooResult: 3 Results filled.\n");
  83.  
  84.       printf("FooResult - Code: [%d]\n", pfoors->ierrorcode);
  85.       printf("FooResult: Version '%d'\n", pfoors->iversion);
  86.       printf("FooResult: (Count: '%d / %d'):\n", pfoors->iresultcount, MAX_RESULT);
  87.  
  88.       for(irs = 0; irs < pfoors->iresultcount; irs++)
  89.       {
  90.           printf("FooResult: Result[%d]: '%d'\n", irs, pfoors->arrresult[irs]);
  91.       }
  92.  
  93.       igtcnt = pfoors->iresultcount;
  94.  
  95.       printf("FooResult: Array getting ...\n");
  96.  
  97.       parrrs = foo_get_result_array(pfoors);
  98.  
  99.       if(parrrs != NULL)
  100.       {
  101.         for(irs = 0; irs < igtcnt; irs++)
  102.         {
  103.                 printf("FooResult: Array[%d]: '%d'\n", irs, *(parrrs + irs));
  104.         }
  105.  
  106.       }
  107.       else  //if(parrrs != NULL)
  108.           printf("FooResult: Array get failed!\n");
  109.  
  110.     }
  111.     else  //if(pfoors != NULL)
  112.       printf("FooResult: Build failed!\n");
  113.  
  114.     printf("FooResult: deleting ...\n");
  115.  
  116.     foo_result_free(pfoors);
  117.  
  118.     printf("FooResult: deleted.\n");
  119.  
  120.         printf("FooResult: App done.\n");
  121.  
  122.   return 0;
  123. }
  124.  

The C Language Host Application can interact with the Library perfectly and reading the field without any issue:

$ ./foo_result
FooResult: building ...
FooResult: built.
FooResult - Debug 0:
FooResult* Debug: '*FooResult { iversion: 0, iresultcount: -1, ierrorcode: 0, arrresult: [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] }'
FooResult - Content:
FooResult - Code: [ 0 ]
FooResult: Version '0'
FooResult: (Count: '-1 / 128'):
FooResult: 3 Results filling ...
FooResult: Result 1 filling ...
FooResult - Debug 1:
FooResult* Debug: '*FooResult { iversion: 1, iresultcount: 1, ierrorcode: 0, arrresult: [1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] }'
FooResult: Result 2 filling ...
FooResult - Debug 2:
FooResult* Debug: '*FooResult { iversion: 2, iresultcount: 2, ierrorcode: 0, arrresult: [1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] }'
FooResult: Result 3 filling ...
FooResult - Debug 3:
FooResult* Debug: '*FooResult { iversion: 3, iresultcount: 3, ierrorcode: 0, arrresult: [1, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] }'
FooResult: 3 Results filled.
FooResult - Code: [ 0 ]
FooResult: Version '3'
FooResult: (Count: '3 / 128'):
FooResult: Result[0]: '1'
FooResult: Result[1]: '2'
FooResult: Result[2]: '3'
FooResult: Array getting ...
FooResult: Array[0]: '1'
FooResult: Array[1]: '2'
FooResult: Array[2]: '3'
FooResult: deleting ...
FooResult: deleted.
FooResult: App done.


Now the corresponding FreePascal Host Application reads only Rubbish.
Which seems to me to be an Issue of Memory Outlay.

The FreePascal Application is this:
Code: Pascal  [Select][+][-]
  1. program demofooresult;
  2.  
  3.  
  4. uses
  5.   SysUtils, ctypes;
  6.  
  7. const
  8.   External_library='libfoo_utils.so'; {Setup as you need}
  9.  
  10. {$IFDEF FPC}
  11. {$PACKRECORDS C}
  12. {$ENDIF}
  13.  
  14.  
  15. const
  16.   MAX_RESULT = 128;
  17.  
  18.  
  19. type
  20.   PFooStruct = Pointer;
  21.  
  22.   PResultArray = ^TResultArray;
  23.   TResultArray = array[0..(MAX_RESULT - 1)] of Int64;
  24.  
  25.   PFooResult = ^TFooResult;
  26.   TFooResult = packed record
  27.     iversion: cuint32;
  28.     iresultcount: cint8;
  29.     ierrorcode: cint8;
  30.     arrresult: TResultArray;
  31.   end;
  32.  
  33.  
  34. function foo_get_result(): PFooResult; cdecl; external External_library name 'foo_get_result';
  35. procedure foo_build_result(pfoo: PFooResult); cdecl; external External_library name 'foo_build_result';
  36. function foo_get_result_array(pfoo: PFooResult): PResultArray; cdecl; external External_library name 'foo_get_result_array';
  37. procedure foo_result_debug(pfoo: PFooResult); cdecl; external External_library name 'foo_result_debug';
  38. procedure foo_result_free(pfoo: PFooResult); cdecl; external External_library name 'foo_result_free';
  39.  
  40.  
  41. var
  42.   pfoors: PFooResult;
  43.   parrrs: PResultArray;
  44.   irs, igtcnt: Integer;
  45. begin
  46.   WriteLn('FooResult: building ...');
  47.  
  48.   pfoors := foo_get_result;
  49.  
  50.   if pfoors <> Nil then
  51.   begin
  52.     WriteLn('FooResult: built.');
  53.  
  54.     WriteLn('FooResult - Debug 0:');
  55.  
  56.     foo_result_debug(pfoors);
  57.  
  58.     WriteLn('FooResult - Content:');
  59.     WriteLn('FooResult - Code: [', pfoors^.ierrorcode, ']');
  60.     WriteLn('FooResult: Version '#39, pfoors^.iversion, #39);
  61.     WriteLn('FooResult: (Count: '#39, pfoors^.iresultcount, ' / ', MAX_RESULT, #39'):');
  62.  
  63.     for irs := 0 to pfoors^.iresultcount - 1 do
  64.       WriteLn('FooResult: Result[', irs, ']: '#39, pfoors^.arrresult[irs], #39'):');
  65.  
  66.     WriteLn('FooResult: 3 Results filling ...');
  67.  
  68.     WriteLn('FooResult: Result 1 filling ...');
  69.  
  70.     foo_build_result(pfoors);
  71.  
  72.     WriteLn('FooResult - Debug 1:');
  73.  
  74.     foo_result_debug(pfoors);
  75.  
  76.     WriteLn('FooResult: Result 2 filling ...');
  77.  
  78.     foo_build_result(pfoors);
  79.  
  80.     WriteLn('FooResult - Debug 2:');
  81.  
  82.     foo_result_debug(pfoors);
  83.  
  84.     WriteLn('FooResult: Result 3 filling ...');
  85.  
  86.     foo_build_result(pfoors);
  87.  
  88.     WriteLn('FooResult - Debug 3:');
  89.  
  90.     foo_result_debug(pfoors);
  91.  
  92.     WriteLn('FooResult: 3 Results filled.');
  93.  
  94.     WriteLn('FooResult - Code: [', pfoors^.ierrorcode, ']');
  95.     WriteLn('FooResult: Version '#39, pfoors^.iversion, #39);
  96.     WriteLn('FooResult: (Count: '#39, pfoors^.iresultcount, ' / ', MAX_RESULT, #39'):');
  97.  
  98.     for irs := 0 to pfoors^.iresultcount - 1 do
  99.       WriteLn('FooResult: Result[', irs, ']: '#39, pfoors^.arrresult[irs], #39);
  100.  
  101.     igtcnt := pfoors^.iresultcount;
  102.  
  103.     WriteLn('FooResult: Array getting ...');
  104.  
  105.     parrrs := foo_get_result_array(pfoors);
  106.  
  107.     if parrrs <> Nil then
  108.     begin
  109.       for irs := 0 to igtcnt - 1 do
  110.         WriteLn('FooResult: Array[', irs, ']: '#39, parrrs^[irs], #39);
  111.  
  112.     end
  113.     else  //if parrrs <> Nil then
  114.       WriteLn('FooResult: Array get failed!');
  115.  
  116.   end
  117.   else  //if pfoors <> Nil then
  118.     WriteLn('FooResult: Build failed!');
  119.  
  120.   WriteLn('FooResult: deleting ...');
  121.  
  122.   foo_result_free(pfoors);
  123.  
  124.   WriteLn('FooResult: deleted.');
  125.  
  126.   WriteLn('App: done.');
  127. end.
  128.  

which prints this Output:

$ ./demofooresult
FooResult: building ...
FooResult: built.
FooResult - Debug 0:
FooResult* Debug: '*FooResult { iversion: 0, iresultcount: -1, ierrorcode: 0, arrresult: [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] }'
FooResult - Content:
FooResult - Code: [ 0 ]
FooResult: Version '0'
FooResult: (Count: '-1 / 128'):
FooResult: 3 Results filling ...
FooResult: Result 1 filling ...
FooResult - Debug 1:
FooResult* Debug: '*FooResult { iversion: 1, iresultcount: 1, ierrorcode: 0, arrresult: [1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] }'
FooResult: Result 2 filling ...
FooResult - Debug 2:
FooResult* Debug: '*FooResult { iversion: 2, iresultcount: 2, ierrorcode: 0, arrresult: [1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] }'
FooResult: Result 3 filling ...
FooResult - Debug 3:
FooResult* Debug: '*FooResult { iversion: 3, iresultcount: 3, ierrorcode: 0, arrresult: [1, 2, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] }'
FooResult: 3 Results filled.
FooResult - Code: [ 0 ]
FooResult: Version '3'
FooResult: (Count: '3 / 128'):
FooResult: Result[0]: '65536'
FooResult: Result[1]: '131072'
FooResult: Result[2]: '196608'
FooResult: Array getting ...
FooResult: Array[0]: '1'
FooResult: Array[1]: '2'
FooResult: Array[2]: '3'
FooResult: deleting ...
FooResult: deleted.
App: done.
Heap dump by heaptrc unit of /plath/to/demofooresult
6 memory blocks allocated : 719/728
6 memory blocks freed     : 719/728
0 unfreed memory blocks : 0
True heap size : 327680
True free heap : 327680


the direct access to TFooResult.arrresult prints only Rubbish although the Array is as Static Array defined:

FooResult - Code: [ 0 ]
FooResult: Version '3'
FooResult: (Count: '3 / 128'):
FooResult: Result[0]: '65536'
FooResult: Result[1]: '131072'
FooResult: Result[2]: '196608'
« Last Edit: January 04, 2021, 05:06:38 pm by domibay_hugo »

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 9285
  • FPC developer.
Re: Imported C Structure is not mapped correctly
« Reply #1 on: January 04, 2021, 04:34:05 pm »
You declare your Pascal structure as packed. You don't declare your C struct as packed.

Solution: declare your C struct as packed by whatever means your C compiler allows.

(or remove the packed and add {$packrecords C} above the record in Pascal, which is the most likely packing default for a C compiler).

domibay_hugo

  • New Member
  • *
  • Posts: 37
  • Site Reliabilty / DevOps Engineer at Domibay S.L.
    • GitHub Profile
Re: Imported C Structure is not mapped correctly
« Reply #2 on: January 04, 2021, 04:48:11 pm »
Thank you very much for this Tip!
the access to the Array TFooResult.arrresult works now correctly.

Although I had the understanding that the packed record definition is required to match with C Language Library Definitions.

I also found that the unit ctypes includes the .inc file /rtl/linux/ptypes.inc
which again defines the directives:
Code: Pascal  [Select][+][-]
  1. {$I ctypes.inc}
  2. {$packrecords c}
  3.  
« Last Edit: January 04, 2021, 04:55:17 pm by domibay_hugo »

PascalDragon

  • Hero Member
  • *****
  • Posts: 2988
  • Compiler Developer
Re: Imported C Structure is not mapped correctly
« Reply #3 on: January 05, 2021, 09:04:14 am »
Although I had the understanding that the packed record definition is required to match with C Language Library Definitions.

No. packed ensures that there is no padding between fields of a record. That is not the case by default in C.

I also found that the unit ctypes includes the .inc file /rtl/linux/ptypes.inc
which again defines the directives:
Code: Pascal  [Select][+][-]
  1. {$I ctypes.inc}
  2. {$packrecords c}
  3.  

That only applies to the records declared inside the ctypes unit (and only if they aren't declared as packed).

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 9285
  • FPC developer.
Re: Imported C Structure is not mapped correctly
« Reply #4 on: January 05, 2021, 09:46:44 am »
Although I had the understanding that the packed record definition is required to match with C Language Library Definitions.

I was not aware that the C language standard said something about packing. Usually standards are very restrictive to specify too much about it.

domibay_hugo

  • New Member
  • *
  • Posts: 37
  • Site Reliabilty / DevOps Engineer at Domibay S.L.
    • GitHub Profile
Re: Imported C Structure is not mapped correctly
« Reply #5 on: January 12, 2021, 04:30:10 pm »
Although I had the understanding that the packed record definition is required to match with C Language Library Definitions.

No. packed ensures that there is no padding between fields of a record. That is not the case by default in C.

I also found that the unit ctypes includes the .inc file /rtl/linux/ptypes.inc
which again defines the directives:
Code: Pascal  [Select][+][-]
  1. {$I ctypes.inc}
  2. {$packrecords c}
  3.  

That only applies to the records declared inside the ctypes unit (and only if they aren't declared as packed).

So, does that mean that Pascal Structures natively map with C Language Structures without the need of the Directive {$packrecords c} or the Keyword packed ?

PascalDragon

  • Hero Member
  • *****
  • Posts: 2988
  • Compiler Developer
Re: Imported C Structure is not mapped correctly
« Reply #6 on: January 13, 2021, 09:01:12 am »
So, does that mean that Pascal Structures natively map with C Language Structures without the need of the Directive {$packrecords c} or the Keyword packed ?

Not necessarily. That's why the {$packrecords c} directive exists. Also packed is only a right choice if the C code enforces 1-Byte alignment as well.

In the end you always need to check what the C code does as it might use a custom alignment (this is for example the case for some structs/records on Windows where the headers enforce a different alignment than the default one and thus the Windows unit changes the {$packrecords xxx} accordingly).

 

TinyPortal © 2005-2018