I've read a piece of Delphi code like this :
sample1 = ARRAY[1..80] OF INTEGER;
psample =^sample1;
VAR
function :ARRAY[1..70] OF psample;
From my understanding, the programmer is trying to declare an array that contains 70 pointers and each pointer points to a sample1 array.
So when I write :
function[1]^[1] := 5;
function[1]^[2] := 10;
then :
function[n]^[1] := 5
function[n]^[2] := 10; ( n = 2 to 70)
Is that correct ?
Your code sample is lacking some information since you do not say how function is defined. This means that you cannot draw the conclusions that you attempt to draw.
Of course, since function is a reserved word in Pascal, that code could never even compile. I will assume now that the variable is called f.
Consider the following definitions:
type
sample1 = array [1..80] of integer;
psample = ^sample1;
var
f : array [1..70] of psample;
Here, sample1 and psample are types. sample1 is type describing an array of 80 integers. psample is a pointer to a sample1.
Next a variable named f is defined. It is an array of 70 psamples.
Now, before you can even consider what happens when you write f[1]^[1], we need to assign some values to the elements of f.
Suppose we did it like this:
var
sample: sample1;
...
for i := 1 to 70 do
f[i] := #sample;
Now it would be true that f[i]^[k] refers to the same integer as f[j]^[k] for all valid i and j. So when you write f[1]^[1] := 42 you are also assigning that value to f[2]^[1], f[3]^[1] and so on.
On the other hand you could do it like this:
var
samples: array [1..70] of sample1;
...
for i := 1 to 70 do
f[i] := #samples[i];
Now each f[i] pointer points to a distinct array in memory. In this case assigning f[1]^[1] := 42 does not modify the value of f[2]^[1] or any of the other values.
That is correct. You have 70 pointers, each pointing to an array of 80 integers.
Related
I need to check if there has been a change in a certain part of the application and therefore I make "copies" of the data after loading them and then compare them. One part of the comparison function involves checking keys in dictionaries like lDict1.Keys.EqualsTo(lDict2.Keys).
Although the dictionaries do not rely on the order of the elements, I didn't realize that even if I fill two dictionaries with the same data, they won't be created the same and the order of elements may change, so the previous function does not work properly because it relies on the elements order that may not match when using any of the following methods. (I'm not sure why)
var
lDict1, lDict2 : IDictionary<Integer, TObject>;
lKey : Integer;
begin
lDict1 := TCollections.CreateDictionary<Integer, TObject>;
lDict1.Add(5, nil); // Keys.First = 5, Keys.Last = 5
lDict1.Add(6, nil); // Keys.First = 5, Keys.Last = 6
lDict2 := TCollections.CreateDictionary<Integer, TObject>;
lDict2.AddRange(lDict1); // Keys.First = 6, Keys.Last = 5
lDict2.Clear;
for lKey in lDict1.Keys do // Keys.First = 6, Keys.Last = 5
lDict2.Add(lKey, nil);
end;
Is there any way to make an exact copy of the dictionary so I can compare them? One way to work around this problem is to create my own comparison function, but I'd like to avoid that.
function ContainsSameValues<T>(AEnumerable1, AEnumerable2: IEnumerable<T>): Boolean;
var
lValue : T;
begin
Result := AEnumerable1.Count = AEnumerable2.Count;
if Result then
begin
for lValue in AEnumerable1 do
begin
Result := AEnumerable2.Contains(lValue);
if not Result then
Exit;
end;
end;
end;
usage
ContainsSameValues<Integer>(lDict1.Keys, lDict2.Keys);
Checking for equality of a unordered dictionaries is a relatively simple algorithm. I will outline it here. Suppose we have two dictionaries, A and B.
Compare the number of elements of A and B. If this differs, the dictionaries are not equal.
Enumerate each key/value pair k,v in A. If k is not in B, or B[k] is not equal to v, then the dictionaries are not equal.
If you reach the end of the enumeration, then you know that the dictionaries are equal.
I have a C DLL with a number of functions I'm calling from Delphi. One of the functions (say Func1) returns a pointer to a struct - this all works fine. The structs created by calling Func1 are stored in a global pool within the DLL. Using a second function (Func2) I get a pointer to a block of memory containing an array of pointers, and I can access the array elements using an offset.
I need to be able copy the address in the returned pointer for a struct (from Func1) to any of the memory locations in the array (from Func2). The idea is that I can build arrays of pointers to pre-defined structs and access the elements directly from Delphi using pointer offsets.
I tried using:
CopyMemory(Pointer(NativeUInt(DataPointer) + offset), PStruct, DataSize);
where DataPointer is the start of my array and PStruct is returned from Func1, but that doesn't copy the address I need.
In .NET it works using Marshal.WriteIntPtr and looking at the underlying code for this using Reflector I think I need something trickier than CopyMemory. Anyone got any ideas for doing this in Delphi?
Edit: This is part of a wrapper around vector structures returned from the R language DLL. I have a base vector class from which I derive specific vector types. I've got the wrapper for the numeric vector working, so my base class looks fine and this is where I get DataPointer:
function TRVector<T>.GetDataPointer: PSEXPREC;
var
offset: integer;
h: PSEXPREC;
begin
// TVECTOR_SEXPREC is the vector header, with the actual data behind it.
offset := SizeOf(TVECTOR_SEXPREC);
h := Handle;
result := PSEXPREC(NativeUInt(h) + offset);
end;
Setting a value in a numeric vector is easy (ignoring error handling):
procedure TNumericVector.SetValue(ix: integer; value: double);
var
PData: PDouble;
offset: integer;
begin
offset := GetOffset(ix); // -- Offset from DataPointer
PData := PDouble(NativeUInt(DataPointer) + offset);
PData^ := value;
end;
For a string vector I need to (i) create a base vector of pointers with a pre-specified length as for the numeric vector (ii) convert each string in my input array to an R internal character string (CHARSXP) using the R mkChar function (iii) assign the address of the character string struct to the appropriate element in the base vector. The string array gets passed into the constructor of my vector class (TCharacterVector) and I then call SetValue (see below) for each string in the array.
I should have thought of PPointer as suggested by Remy but neither that or the array approach seem to work either. Below is the code using the array approach from Remy and with some pointer vars for checking addresses. I'm just using old-fashioned pointer arithmetic and have shown addresses displayed for a run when debugging:
procedure TCharacterVector.SetValue(ix: integer; value: string);
var
PData: PSEXPREC;
offset: integer;
offset2: integer;
PTest: PSEXPREC;
PPtr: Pointer;
PPtr2: Pointer;
begin
offset := GetOffset(ix);
PPtr := PPointer(NativeUInt(DataPointer) + offset); // $89483D8
PData := mkChar(value); // $8850258
// -- Use the following code to check that mkChar is working.
offset2 := SizeOf(TVECTOR_SEXPREC);
PTest := PSEXPREC(NativeUInt(PData) + offset);
FTestString := FTestString + AnsiString(PAnsiChar(PTest));
//PPointerList(DataPointer)^[ix] := PData;
//PPtr2 := PPointer(NativeUInt(DataPointer) + offset); // Wrong!
PPointerArray(DataPointer)^[ix] := PData;
PPtr2 := PPointerArray(DataPointer)^[ix]; // $8850258 - correct
end;
I'd have thought the address in PData ($8850258) would now be in PPtr2 but I've been staring at this so long I'm sure I'm missing something obvious.
Edit2: The code for SetValue used in R.NET is as follows (ignoring test for null string):
private void SetValue(int index, string value)
{
int offset = GetOffset(index);
IntPtr stringPointer = mkChar(value);
Marshal.WriteIntPtr(DataPointer, offset, stringPointer);
}
From reflector, Marshal.WriteIntPtr uses the following C:
public static unsafe void WriteInt32(IntPtr ptr, int ofs, int val)
{
try
{
byte* numPtr = (byte*) (((void*) ptr) + ofs);
if ((((int) numPtr) & 3) == 0)
{
*((int*) numPtr) = val;
}
else
{
byte* numPtr2 = (byte*) &val;
numPtr[0] = numPtr2[0];
numPtr[1] = numPtr2[1];
numPtr[2] = numPtr2[2];
numPtr[3] = numPtr2[3];
}
}
catch (NullReferenceException)
{
throw new AccessViolationException();
}
}
You say you want to copy the struct pointer itself into the array, but the code you have shown is trying to copy the struct data that the pointer is pointing at. If you really want to copy just the pointer itself, don't use CopyMemory() at all. Just assign the pointer as-is:
const
MaxPointerList = 255; // whatever max array count that Func2() allocates
type
TPointerList = array[0..MaxPointerList-1] of Pointer;
PPointerList = ^TPointerList;
PPointerList(DataPointer)^[index] := PStruct;
Your use of NativeUInt reveals that you are using a version of Delphi that likely supports the {$POINTERMATH} directive, so you can take advantage of that instead, eg:
{$POINTERMATH ON}
PPointer(DataPointer)[index] := PStruct;
Or, use the pre-existing PPointerArray type in the System unit:
{$POINTERMATH ON}
PPointerArray(DataPointer)[index] := PStruct;
I am trying to get Unicode font glyph ranges (Delphi 6):
var GS:PGlyphSet;
GSSize:LongWord;
rng:TWCRange;
begin
GSSize := GetFontUnicodeRanges(Canvas.Handle, nil);
GetMem(Pointer(GS), GSSize);
try
GS.cbThis:=GSSize;
GS.flAccel:=0;
GS.cGlyphsSupported:=0;
GS.cRanges:=0;
if GetFontUnicodeRanges(Canvas.Handle, GS)<>0 then begin
for i:=0 to GS.cRanges-1 do begin
rng := GS.ranges[i];
The strange thing is that Length(GS.ranges) is 1, but GS.cRanges is 309 and when I try to access the second range GS.ranges[1] I get, of course, a range check error. Before I turned range checking on it has worked in some magical way.
Types for reference (from Windows module):
PWCRange = ^TWCRange;
{$EXTERNALSYM tagWCRANGE}
tagWCRANGE = packed record
wcLow: WCHAR;
cGlyphs: SHORT;
end;
TWCRange = tagWCRANGE;
PGlyphSet = ^TGlyphSet;
{$EXTERNALSYM tagGLYPHSET}
tagGLYPHSET = packed record
cbThis: DWORD;
flAccel: DWORD;
cGlyphsSupported: DWORD;
cRanges: DWORD;
ranges: array[0..0] of TWCRange;
end;
TGlyphSet = tagGLYPHSET;
This struct makes use of the so-called struct hack:
http://c-faq.com/struct/structhack.html
http://tonywearme.wordpress.com/2011/07/26/c-struct-hack/
The ranges member is a variable length array, placed inline in the struct. But you cannot actually encode that in a static C type. That's why you call the function to find out how much memory to allocate, and then heap allocate the struct. If you allocated it on the stack, or using SizeOf(...) then the struct would be too small.
The simplest thing to do is to disable range checking for the code that accesses ranges. Although the type declaration says that only 0 is a valid index for ranges, in fact 0..cRanges-1 are valid.
If you don't want to disable range checking for the relevant code, then take a pointer the element 0, and then use pointer arithmetic in your loop.
var
rng: PWCRange;
....
rng := #GS.ranges[0];
for i:=0 to GS.cRanges-1 do begin
// use rng^
inc(rng);
end;
This is, in my view, the cleanest way to write code for sequential access. For random access, and with range checking in force, you'd be compelled to declare some extra types to defeat range checking:
type
TWCRangeArray = array [0..(MaxInt div SizeOf(TWCRange))-1] of TWCRange;
PWCRangeArray = ^TWCRangeArray;
And then use type casting to access individual elements:
rng := PWCRangeArray(#GS.ranges)[i];
I am a student in high school and I am currently learning in Delphi XE3. We are learning about BIT manipulation. We have an assignment and while I have read a lot on the subject and understand the entire process of storing information in Bits and SHL/SHR I am having difficulty understanding how to do this process in Delphi.
The assignment is as follows:
Decimal Hexidecimal Binary
1 0x0001 0000000000000001
2 0x0002 0000000000000010
4 0x0004 0000000000000100
Passing an integer value in an XML file to identify the options set. For example. If I wanted to send option 1 and option 2, I would add 1+2=3. I would send 3 as the number to specify that options 1 and 2 are true.
On the client the binary value would be 0000000000000011 = 3
From what I have read I need to use a mask but I do not understand how to do this. How would do I use masks in Delphi ot obtain the individual values which would be True or False.
I tried doing this in a regular Integer variable but it always gets treated as an Integer and the result is very strange. If I convert the integer to a binary string representation and I iterate thru the characters the result is correct but I am assuming that I should not be doing this with strings. Any help or an example would be greatly appreciated. Thank you.
You usually check if a particular bit is set in a Integer variable using the and binary operator, and you set individual bits using the or operator, like this:
const
OPTION_X = $01;
OPTION_Y = $02;
OPTION_Z = $04;
var
Options: Byte;
begin
Options := OPTION_X or OPTION_Y; //actually 3, like in your example
//check if option_X is set
if (Options and OPTION_X) = OPTION_X then
ShowMessage('Option X is set'); //this message is shown, because the bit is set
//check if option_Z is set
if (Options and OPTION_Z) = OPTION_Z then
ShowMessage('Option Z is set'); //this message is NOT shown
end;
The different OPTION_ constants, are actually masks, in the sense they are used to mask bits to zero (to check if a particular bit is set) or to mask bits to 1 (to set a particular bit).
Consider this fragment:
begin
..
if cbOptionX.Checked then
Options := Options or OPTION_X;
..
the or will mask the first bit to 1. If we start with a Options value (in binary) of 01010000, the resulting Options would be 01010001
01010000
OR 00000001 //OPTION_X
= 01010001
the same value is used to mask all the other bits to 0 to check if a particular bit is set. The if condition, for example: (Options and OPTION_Z) = OPTION_Z, does this:
first it MASKS all the non-interesting bytes of the Option variable to 0. If we consider the last value of 01010001, the operation will result in clearing all the bits, but the first.
01010001
AND 00000001
= 00000001
considering a starting value of 01010000 it will return zero:
01010000
AND 00000001
= 00000000
next, it compares if that value is equal to the mask itself. If it is equal, the bit was set in the original Options variable, otherwise it was not set. If your mask contains only one bit, that's matter of taste, you can just check if the resulting value is, for example, different than 0, but if your mask contains multiple bits and you want to check if all the bits was set, you have to check for equality.
Delphi has a predefined type TIntegerSet which allows to use set operators. Assuming that options is an Integer, you can check if any bit (0-based) is set like this:
option1 := 0 in TIntegerSet(options); { Bit 0 is set? }
option3 := 2 in TIntegerSet(options); { Bit 2 is set? }
Changing the options is done via Include or Exclude:
Include(TIntegerSet(options), 0); { set bit 0 }
Exclude(TIntegerSet(options), 2); { reset bit 2 }
Of course you can use any other set operator that may be helpful.
Delphi has Bitwise Operators for manipulating individual bits of integer types. Look at the shl, shr, and, or, and xor operators. To combine bits, use the or operator. To test for bits, use the and operator. For example, assuming these constants:
const
Option1 = 0x0001;
Option2 = 0x0002;
Option3 = 0x0004;
The or operator looks at the bits of both input values and produces an output value that has a 1 bit in places where either input value has a 1 bit. So combining bits would look like this:
var
Value: Integer;
begin
Value := Option1 or Option2;
{
00000000000000000000000000000001 Option1
00000000000000000000000000000010 Option2
-------------------------------- OR
00000000000000000000000000000011 Result
}
...
end;
The and operator looks at the bits of both input values and produces an output value that has a 1 bit only in places where both input value have a 1 bit, otherwise it produces a 0 bit instead. So testing for bits would look like this:
var
Value: Integer;
Option1Set: Boolean;
Option2Set: Boolean;
Option3Set: Boolean;
begin
Value := 7; // Option1 or Option2 or Option3
Option1Set := (Value and Option1) = Option1;
{
00000000000000000000000000000111 Value
00000000000000000000000000000001 Option1
-------------------------------- AND
00000000000000000000000000000001 Result
}
Option2Set := (Value and Option2) = Option2;
{
00000000000000000000000000000111 Value
00000000000000000000000000000010 Option2
-------------------------------- AND
00000000000000000000000000000010 Result
}
Option3Set := (Value and Option3) = Option3;
{
00000000000000000000000000000111 Value
00000000000000000000000000000100 Option3
-------------------------------- AND
00000000000000000000000000000100 Result
}
...
end;
I'm tryin to scan an entire process memory but no success... What I'm doing is: for tests I'm using notepad, so I write there %B and this values in HEX are: 25(%) and 42(B). So the code is:
while (VirtualQueryEx(PIDHandle, Pointer(MemStart), MemInfo, SizeOf(MemInfo)) <> 0) do
begin
if ((MemInfo.State = MEM_COMMIT) and (not (MemInfo.Protect = PAGE_GUARD)
or (MemInfo.Protect = PAGE_NOACCESS)) and (MemInfo.Protect = PAGE_READWRITE)) then
begin
SetLength(Buff, MemInfo.RegionSize);
if (ReadProcessMemory(PIDHandle, MemInfo.BaseAddress, Buff,
MemInfo.RegionSize, ReceivedBytes)) then
begin
for I := 0 to SizeOf(Buff) do
begin
if (IntToHex(Buff[i], 1) = '25') and (IntToHex(Buff[i+2], 1) = '42') then
Form1.Memo1.Lines.Append(IntToHex(Buff[i], 1));
end;
end;
end;
MemStart:= MemStart + MemInfo.RegionSize;
end;
CloseHandle(PIDHandle);
end;
The var 'Buff' is TBytes (I read about TBytes and think it's same as array of byte). So I'm converting the bytes to Hex, and searching for values: 25 and 42 respectively. The code is like:
if (IntToHex(Buff[i], 1) = '25') and (IntToHex(Buff[i+2], 1) = '42') then
Because have 00 between the hex values. So I need to add '+2'. How can I scan the entire memory for this values??
Notepad uses Unicode so you'll need to look for UTF-16 encoded data, $0025 and $0042.
I don't understand why you feel the need to convert into hex strings before comparing. There's nothing special about hex that requires the use of strings. Hexadecimal is just a number system with base-16. So, decimal 32 is the same as hexadecimal 20, i.e. 32=$20. Do your comparison directly with integral values:
if (Buff[i]=$25) and (Buff[i+2]=$42) then
That said, taking into account the $00 bytes your test should really be something like this:
var
Target: string;
....
Target := '%B';
if CompareMem(#Buff[i], #Target[1], Length(Target)*SizeOf(Char)) then
....
I don't want to get too deep into the rest of your code, but this line
for I := 0 to SizeOf(Buff) do
is wrong on many different levels.
SizeOf(Buff) returns the size of a pointer since a dynamic array variable is essentially just a pointer. A useful thing to remember is that SizeOf is evaluated at compile time.
If you used Length instead of SizeOf then you would be iterating over the end of the list. To loop over a dynamic array, loop from 0 to Length(...)-1.
But in this case you are accessing index i+2 inside the loop, so you should loop from 0 to Length(...)-3.
But in fact you need to compare against 4 consecutive bytes to find a match. Perhaps like this:
TargetByteLength = Length(Target)*SizeOf(Char);
for i := 0 to Length(Buff)-TargetByteLength do
if CompareMem(#Buff[i], #Target[1], TargetByteLength) then
....