Defining a subset of an array

Hi, need to pass an array to a C compiled ddl, read the returned array and break it up into 4 smaller arrays.

The array I want to read back, is one long array, containing 4 sets of smaller arrays. I want to assign the address of the first element of each subset of data to a variable (of type array) so that I have 4 smaller arrays.

Consider the sample code:

const
        Samples = 10;
type
        TArray = array of Double;
var
 Data, Data0, Data1, Data2, Data3: ^TArray;
begin
 SetLength(Data^, 4*Samples);

//The actual Delphi call to the C DLL
//function DAQmxReadAnalogF64(taskHandle:Longint; numSampsPerChan:Longint; timeout:Double; fillMode:DAQmxFillMode;var readArray: Double; arraySizeInSamps:Longint; var sampsPerChanRead:Longint; reserved:Pointer):Longint; stdcall;
//"var readArray: Double;" is the variable in question

//Pass the address of element 0 of the array the contain all 40 data points
 ReadData(Data^[0]); //Actual declaration: ReadData(var Data : array of double);
//Set the address of Data0, the fisrt 10 data points
 Data0 := Data;
 SetLength(Data0^, Samples);

//Set the address of Data1, the second 10 data points
 Data1 := Data^[10];
 SetLength(Data1^, Samples);

//Set the address of Data2, the third 10 data points
 Data2 := Data^[20];
 SetLength(Data2^, Samples);

//Set the address of Data3, the forth 10 data points
 Data3 := Data^[30];
 SetLength(Data3^, Samples);
end;//The code above does not work in practise, but I'd it to be implemented in a simular manner

//This is how I can get it to work
const
        Samples = 10;
type
        TArray = array of Double;
var
 Data, Data0, Data1, Data2, Data3: TArray;
 n: integer;
begin
 SetLength(Data^, 4*Samples);

//Pass the address of element 0 of the array the contain all 40 data points
 ReadData(Data^[0]);
//Set the address of Data0, the fisrt 10 data points
 Data0 := Data;
 SetLength(Data0^, Samples);

 SetLength(Data1^, Samples);
 SetLength(Data2^, Samples);
 SetLength(Data3^, Samples);

        for n := 0 to 9 do
        begin
         Data1^[n] := Data^[n+10];
         Data2^[n] := Data^[n+20];
         Data3^[n] := Data^[n+30];
        end;
end;


This is a problem as I need to process up to 5E6 for each data set


cfmAsked:
Who is Participating?
 
2266180Connect With a Mentor Commented:
you won't be able to do that with just dynamic arrays since they are not just a series of elements in the memory. there is otehr information saved as well.

shortly:
- the data starts at @a[0]
- the data about teh array (length, element size?, etc) is stored at @a
- if you get the address of element X from the array, you still need a valid address for the dynamic array itself in order to cast and successfully use.

the workaround is to use static arrays. small example:

procedure TForm1.FormCreate(Sender: TObject);
type TElement=integer;
     PArray=^Tarray;
     TArray=array [0..30000] of TElement;
var a:TArray;
    i:integer;
    s:array[1..4] of PArray;
    ss:string;
    l:integer;
begin
  l:=16;
  for i:=1 to l do// initialize some test data
    a[i-1]:=i;
  for i:=1 to 4 do// initialize the subsets
    s[i]:=pointer(integer(@a[0])+(i-1)*(l div 4){the number of elements in the subset}*sizeof(TElement){the length of the type of the elements});
  ss:='';
  for i:=1 to 4 do// show the first element of each subset
    ss:=ss+inttostr(s[i]^[0])+' ';
  showmessage(ss);
end;
0
 
Pierre CorneliusCommented:
It seems your returned array is of fixed length i.e. 40 bytes and you want to reference it as 4 separate arrays each of 10 bytes. If my understanding is correct, then you simply need to use a multidimensional array to reference the data accordingly. Something like this:

var
  Data: array[1..4, 1..10] of double;
begin
  after your call to DAQmxReadAnalogF64 the Data variable can be referenced as follows:
  Data[1,1] = data set 1 point 1
  Data[1,2] = data set 1 point 2
  Data[2,1] = data set 2 point 1
  Data[3,1] = data set 3 point 1
  etc.

another option is to structure the data something like this:

type
  TDataPoints = array[1..10] of double;
  TDataPointsSet = array[1..4] of TDatapoints;


Let me know if you need more info.

Regards
Pierre
0
 
alkisgCommented:
IF Samples is constant, you may also use a record:

const
  Samples = 10;
type
  MyArray = packed record
     case byte of
        0: (a: array[1..4*Samples] of integer);
        1: (b, c, d, e: array [1..Samples of integer);
  end;

In this case, record.a overlaps with record.b, record.c, record.d and record.e so it does what you want with an easier syntax:
with record do
begin
   a[1] := ...
   b[1] := ...
end;

I like the other (Ciuly's and Pierre's) ideas better, though! :-)
0
 
cfmAuthor Commented:
PierreC and alkisq

Did try playing with multidimensional arrays and records earlier.  Ran into trouble getting the variable accepted by the function in the dll.
0
 
2266180Commented:
I'm just curious: what wasn't good enough?
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.