Recent

Author Topic: [SOLVED] How to declare an array of variable size?  (Read 391 times)

Gizmo

  • Hero Member
  • *****
  • Posts: 682
[SOLVED] How to declare an array of variable size?
« on: September 03, 2019, 12:17:21 pm »
I'm not sure if I am going crazy or just entirely forgetful, but if you need to declare a buffer that could be of any size, from just a few bytes, to several Mb, how do you declare that in the var section, given it can't be of a fixed size but needs to be specified as a fixed size in the var section?

Basically I have a function that gets the filesize of a file using one API call. The value is stored in integer ItemSize. I then need to call another API function that reads the specified file and returns the bytes read into a buffer. But how do I ensure the buffer is large enough for the bytes read?

I think I am overthinking it or forgetting something basic, but I tried writing a function that first prepared the buffer like this :

Code: Pascal  [Select]
  1. function PrepareBuffer(RequiredSize : integer) : array of byte; stdcall; export;
  2. var
  3.   DataBuf : array [0..RequiredSize-1] of byte;
  4. begin
  5.   // Make the buffer equal in size to the file that is about to be read
  6.   FillChar(DataBuf, RequiredSize, #00);
  7.   result := DataBuf;
  8. end;
  9.  
  10. function MainFunc....
  11. var
  12.   DataBuf      : array of byte;  // How do I declare the array size to be whatever size is later needed by the total bytes read in the file?
  13. begin
  14. ...
  15.   ItemSize := APICall_GetItemSize(Item); // Get the file size of the specified file item
  16.   DataBuf := PrepareBuffer(ItemSize);   // Prepare the buffer to be equal in size for the file about to be read
  17.   intBytesRead := APICall_Read(Item, 0, @DataBuf, ItemSize);    // Read the file data into the buffer
  18. ...
  19.  

but it tells me the array of byte is not a type identifier? Apparantly you need to create your own class of array when returning them as a function result?
« Last Edit: September 03, 2019, 03:12:33 pm by Gizmo »
Lazarus 2.0.2 and fpc 3.0.4 - Linux Mint 19 LTS, Windows 10 64 and Mac OSX Majove
Useful Page to remember : http://wiki.freepascal.org/Cross_compiling#From_Linux_x64_to_Linux_i386

Xor-el

  • Sr. Member
  • ****
  • Posts: 371
Re: How to declare an array of variable size?
« Reply #1 on: September 03, 2019, 01:41:12 pm »
but it tells me the array of byte is not a type identifier? Apparantly you need to create your own class of array when returning them as a function result?

In this context, you can use TBytes since this is defined as an array of byte internally and resize it using SetLength to a size of your choice.
« Last Edit: September 03, 2019, 01:44:38 pm by Xor-el »

Thaddy

  • Hero Member
  • *****
  • Posts: 8950
Re: How to declare an array of variable size?
« Reply #2 on: September 03, 2019, 01:44:36 pm »
I don't know what you are exactly looking for, but dynamic arrays can be ragged arrays. (and I already posted demo's on this forum)
Most people that want to use threading should learn to patch their jeans first: use a needle.

Gizmo

  • Hero Member
  • *****
  • Posts: 682
Re: How to declare an array of variable size?
« Reply #3 on: September 03, 2019, 02:29:02 pm »
Thanks Xor-el. TBytes does compile OK, but the problem I have still continues.

Basically, I am caling an API of a propriatory software tool. Two of the API calls allows a programmer to get a file size, and read the file.

I get the file size first. That works OK. example : 162,273 bytes.

I then make the read call, which is supposed to read 162273 bytes of data from the file, into the buffer. But I've spent 3 hours wrestling with it and I just keep getting the SIGSEV error that is always generated when you try and pass either the wrong amount or the wrong thing to the wrong place.

The API read call I am trying to use is structured like this :

DWORD API_Read(
   HANDLE hItem,
   INT64 nStartOffset,
   LPVOID lpBuffer,
   DWORD nNumberOfBytesToRead,
);

So, file item number, starting offset, buffer to put data in, amount of data to put in it.

So, if you know the file size is assigned and reporting to be 162273, and you know the handle to the file item is valid, why on earth does this not just put in 162273 bytes from offset 0 into DataBuf?

 intBytesRead := API_Read(Item, 0, @DataBuf, ItemSize);   
Lazarus 2.0.2 and fpc 3.0.4 - Linux Mint 19 LTS, Windows 10 64 and Mac OSX Majove
Useful Page to remember : http://wiki.freepascal.org/Cross_compiling#From_Linux_x64_to_Linux_i386

bytebites

  • Full Member
  • ***
  • Posts: 206
Re: How to declare an array of variable size?
« Reply #4 on: September 03, 2019, 03:06:10 pm »
Code: Pascal  [Select]
  1.  intBytesRead := API_Read(Item, 0, @DataBuf[0], ItemSize);  
  2.  

Gizmo

  • Hero Member
  • *****
  • Posts: 682
Re: How to declare an array of variable size?
« Reply #5 on: September 03, 2019, 03:12:23 pm »
 :D :D :D

OMG...I am so embarrased! That's what happens when you take a few months off coding! Yeah, the
Code: [Select]
@DataBuf[0] position assignment was missing! So that fixed that error. Thanks man.

And yes, using TBytes with SetLength has enabled my variable sized array. Thanks all
« Last Edit: September 03, 2019, 03:25:09 pm by Gizmo »
Lazarus 2.0.2 and fpc 3.0.4 - Linux Mint 19 LTS, Windows 10 64 and Mac OSX Majove
Useful Page to remember : http://wiki.freepascal.org/Cross_compiling#From_Linux_x64_to_Linux_i386

PascalDragon

  • Hero Member
  • *****
  • Posts: 630
  • Compiler Developer
Re: [SOLVED] How to declare an array of variable size?
« Reply #6 on: September 09, 2019, 10:23:05 am »
but it tells me the array of byte is not a type identifier? Apparantly you need to create your own class of array when returning them as a function result?
If you want to use dynamic arrays as a type in a function's parameter list or the result type you need to declare a corresponding dynamic array type or use an existing one. This is because the syntax for dynamic arrays is used for open array parameters (which are similar, but different) and this won't work for the function result.
Code: Pascal  [Select]
  1. type
  2.   TLongIntArray = array of LongInt;
  3.  
  4. function MyFunction: TLongIntArray;
  5. // an alternative is to use the generic TArray:
  6. function MyFunction2: specialize TArray<LongInt>; // without "specialize" in mode Delphi of course

By the way: you don't need to declare your PrepareBuffer function as stdcall; export; if you aren't exporting them from a library. And even then you shouldn't export functions from libraries that use managed types like strings or dynamic arrays if you don't know exactly what you're doing.