Delphi Typed Pointer made easy.
It is just a small unit for creating an array of a certain type at runtime, forget the GetMem()
and FreeMem()
and try..finally
block.
Usually when an array is needed to be used as a pointer, we must allocate a memory block representing the array by using the GetMem()
or alloc()
by specifing element's size times the number of elements, then call FreeMem()
to free up the memory.
This will result in this boring code.
var
pWordArray: PWord;
begin
pWordArray := GetMem(SizeOf(Word) * 10); // create 10 elements of Word
try
// Do something with the memory
finally
FreeMem(pWordArray);
end;
end;
This unit helps eliminate that long code blocks into a single line.
pWordArray := TRecordArray<PWord>.Create(10); // create a memory block for array of 10 words.
Yes, we can use dynamic array instead of manually allocating/deallocating the memory, but Delphi's dynamic array has its own memory layout and byte alignment, which sometimes incompatible with most C API.
- Work with any pointer types.
- Flat memory layout, no byte alignment (packed)
- Suitable for using with Win/C API.
- Automatic reference counting (via Interface/COM), auto release memory.
- Accessing element without doing pointer math.
- Memory re-allocation, resizable array.
var
WordArray: IRecordArray<PWord>; // IRecordArray enables auto-release feature.
begin
WordArray := TRecordArray<PWord>.Create(10); // Create an array with 10 elements of Word
// WordArray will be automatically deallocated when the function exit or no longer used.
end;
The data is stored in memory as little-endian on x86-64 CPU
If the data is already allocated somewhere else, just put the pointer to that data and specify the length directly.
var
WordArray: IRecordArray<PWord>;
begin
WordArray := TRecordArray<PWord>.Create(PointerToWords, 10); // Create an array with 10 elements of Word using a pointer.
end;
WordArray.Length
WordArray.Length := WordArray.Length + 5; // Expand 5 elements
WordArray.Length := WordArray.Length - 5; // Shrink the last 5 elements
var
I: Integer;
begin
for I := 0 to WordArray.Length - 1 do
DoSomethingWithWord(WordArray[I]^);
end;
WordArray.ElementSize
WordArray.DataSize
WordArray.Data
WordArray.Append(AnotherWordArray)
A record type must has its pointer type declared.
type
TMyRecord = packed record
Value1: Integer;
Value2: Integer;
end;
PMyRecord = ^TMyRecord;
var
MyRecordArray: IRecordArray<PMyRecord>;
I: Integer;
begin
MyRecordArray := TRecordArray<PMyRecord>.Create(100);
for I := 0 to MyRecordArray.Length - 1 do
begin
MyRecordArray[I].Value1 := I * 5;
MyRecordArray[I].Value2 := I * 10;
end;
end;