void method (void *pixels); to delphi declaration - delphi

How should such declaration be converted to delphi?
void method (void *pixels);
And I have also the information that I should pre-allocate that variable.
could someone give me a hint?

If you need to stick to the original declaration format (as for example when converting C DLL headers), and the conversion would be:
procedure method(pixels: Pointer);
You can find dome more information on converting C headers to Delphi here
On the other hand, if you are converting the whole method or class you might want to adapt it to a more Delphi-like code. I do not know what "pixels" is, so I can hardly guess which would be the best option.
On a wild guess, if it is a matrix with some information about each pixel (position, color, alpha channel?) you can easily handle such a structure like that with object lists or create your own class to handle it.
HTH

Assuming that pixels points to an array of pixels, you could do:
procedure method(var pixels); cdecl;
If you passed pixels as untyped parameter, it is implicitly passed as pointer, which is what the C declaration does too, so the conversion matches the original perfectly. Using an untyped pointer enables you to cast it to anything you like or take its address to get the pointer. As long as you know the structure of pixels, that may be more convenient:
Let's assume pixels is a fixed size array of byte, where each bit is a pixel:
type
TPixels = array[0..7] of Byte;
const
Grey: TPixels = ($55, $AA, $55, $AA, $55, $AA, $55, $AA);
procedure method(var pixels); cdecl;
begin
Move(Grey, pixels, Sizeof(Grey));
// ...
TPixels(pixels)[3] := $FF;
// ...

Related

Memory copy and memory compare array of array of Single

In Delphi, I declared a 3x3 matrix table as an array of array of Single, like this:
m_Table: array [0..2] of array [0..2] of Single;
Now I want to memory compare the content with another table, or memory copy the table content from another table. I know that I can create a nested loop to do that, but I want to do the job without any loop, if possible.
My question is, it is correct to copy or compare the memory like this:
CompareMem(m_Table, other.m_Table, 9 * SizeOf(Single));
CopyMemory(m_Table, other.m_Table, 9 * SizeOf(Single));
If not, what is the correct way to do that?
And as a subsidiary question, is there a better way to get the length to copy instead of 9 * SizeOf(Single), like e.g. SizeOf(m_Table^)?
Regards
The code in the question works fine. Personally I would say that Move is the idiomatic way to copy memory. Further I would use SizeOf(m_Table) to obtain the size of the type.
I would point out that your comparison differs from the floating point equality operator. Perhaps that's what you want, but you should be aware of this. For instance zero and minus zero compare equal using floating point comparison but not with memory compare. And NaNs always compare not equal, even with identical bit patterns.
Let me also comment that it would make your code more extendible if you declared a type for these matrices. Without that you won't be able to write functions that accept such objects.
The correct and easiest way may be to define a type:
type
TMatrix3x3 = array [0..2,0..2] of Single;
Then you can directly write:
var
v1, v2: TMatrix3x3;
begin
fillchar(v1,sizeof(v1),0);
move(v1,v2,sizeof(v1));
if comparemem(#v1,#v2,sizeof(v1)) then
writeln('equals');
end;
Using sizeof() make your code safe and readable.
You may define a wrapper type with methods:
{ TMatrix3x3 }
type
TMatrix3x3 = record
v: array [0..2,0..2] of Single;
procedure Zero;
procedure Copy(var dest: TMatrix3x3);
procedure Fill(const source: TMatrix3x3);
function Equals(const other: TMatrix3x3): boolean;
end;
procedure TMatrix3x3.Copy(var dest: TMatrix3x3);
begin
move(v,dest,sizeof(v));
end;
function TMatrix3x3.Equals(const other: TMatrix3x3): boolean;
begin
result := CompareMem(#v,#other.v,sizeof(v));
end;
procedure TMatrix3x3.Fill(const source: TMatrix3x3);
begin
move(source,v,sizeof(v));
end;
procedure TMatrix3x3.Zero;
begin
fillchar(v,sizeof(v),0);
end;
Including then advanced features like implicit assignment, and operators, if needed.
But don't reinvent the wheel, if you really to work with matrix arithmetic. Use an already existing and fully tested library, which will save you a lot of trouble and debugging time.
You should use standard TMatrix type from System.Math.Vectors unit, then you can just compare it directly as if Matrix1 = Matrix2 then and assign as Matrix1 := Matrix2

Can I force `const` to pass by reference (aka the missing `in` parameter)

Delphi has:
var : pass by reference; parameter is both input and output.
out : pass by reference; parameter is output only.
const: pass by ..... well it depends; parameter is input only.
in : pass by reference; parameter is input only and will not be changed there is no "in".
I don't mind that there is no spoon, but I miss in; considering the following code, is there a cleaner way of doing this?
type TFastDiv = record
strict private
FBuffer: Int64;
other fields
....
//Must be `var` because `const` would pass a Int64 by value
// |||
// VVV
function DivideFixedI32(var Buffer: Int64; x: integer): integer;
asm
mov r9,rcx
imul dword ptr[rcx] // do stuff with the buffer
..
mov ecx, [r9+4] // do other stuff with the rest of the buffer
{Changing the code to imul ecx;...;shr r9,32;mov ecx,r9d would allow pass by value, but let's assume the code must not be changed.}
class operator TFastDiv.IntDivide(x:integer; const buffer:TFastDiv):integer;
begin
Result:= DivideFixedI32(Int64((#buffer.FBuffer)^), abs(x)); <<-- Ugly
if (x < 0) then Result:= - Result;
end;
DivideFixed will never change the buffer. The whole point of the routine is that buffer is a precalculated value that does not change.
In the class operator I declare buffer as const, because the record must not change.
The question is:
If I insist on declaring the buffer parameter in IntDivide as const is there a cleaner way of coding or am I stuck in the pointer_to/points_to hack?
Newer compiler versions (from XE3 onwards) support the [Ref] decorator:
procedure Foo(const [Ref] Arg1: Integer; [Ref] const Arg2: Byte);
Example adapted from the documentation, which emphasises the [Ref] can go either before or after the const keyword.
The only option (pre Delphi XE3) if you want to ensure pass-by-reference, is to pass something big.
i.e. bigger than sizeof(pointer)
type TFastDiv = record
strict private
FBuffer: Int64; <<-- make sure this is the first member
other fields
....
function DivideFixedI32(const Buffer: TFastDiv; x: integer): integer;
...
class operator TFastDiv.IntDivide(x:integer; const buffer:TFastDiv):integer;
begin
Result:= DivideFixedI32(buffer, abs(x));
This line in the Delphi help file:
Sets, records, and static arrays of 1, 2, or 4 bytes are passed as 8-bit, 16-bit, and 32bit values. Larger sets, records, and static arrays are passed as 32-bit pointers to the value. An exception to this rule is that records are always passed directly on the stack under the cdecl, stdcall, and safecall conventions; the size of a record passed this way is rounded upward to the nearest double-word boundary.
is misleading and should be changed to/read as:
Sets, records, and static arrays up to SizeOf(pointer) are passed as 8-bit, 16-bit, and 32bit values (64 bit values on x64). Sets, records, and static arrays larger than SizeOf(Pointer) are passed as pointers to the value. An exception to this rule is that records are always passed directly on the stack under the cdecl, stdcall, and safecall conventions; the size of a record passed this way is rounded upward to the nearest SizeOf(pointer) boundary.

Delphi compiler error E2064 left side cannot be assigned to

I inherited a Delphi application and I know nothing about object pascal.
It's a BPL that I need to compile into the new version of C++ Builder XE.
When I run a make I get the error:
E2064 left side cannot be assigned to.
I've learned enough obj pascal to know I have a constant that is trying to be assigned a value.
But, apparently, you can over ride this behanvior; essentially turning constants into vars by going into Build options under the Delphi compiler and turning on "Assignable Typed constants".
I did that and I continue to get the same error.
I tried surrounding my code with {$J+} and {$J-} and still it will not compile.
procedure TChunkIDAT.CopyInterlacedRGB8(const Pass: Byte;
Src, Dest, Trans{$IFDEF Store16bits}, Extra{$ENDIF}: pChar );
var
Col: Integer;
begin
{Get first column and enter in loop}
Col := ColumnStart[Pass];
Dest := pChar(Longint(Dest) + Col * 3);
repeat
{Copy this row}
Byte(Dest^) := fOwner.GammaTable[pByte(Longint(Src) + 2)^]; inc(Dest);
Get the error on last line. If I change the const to a var, I then get the error that the declaration differs from the previous declaration but I have no idea where the previous declaration is....
You're type-casting a two-byte thing (Char) into a one-byte thing (Byte). Reading that value is easy to define, but making that value writable is tricky, probably for the same reason the types of formal and actual "var" parameters need to be identical.
Maybe you wanted to type-cast it to a two-byte thing, such as Word. Or maybe you want GammaTable to be an array of Char so you don't have to type-cast at all. Or maybe, if this code was originally written for a Delphi version earlier than 2009, you want those PChar declarations to be PAnsiChar — character types have gotten wider. Another option is to type-cast Dest to PByte, and then dereference the result. That's probably a bad idea, though, because you'll only be overwriting every other byte of the buffer.
Based on the name of the function, it sounds like PChar was never the right data type to use. That type is for character data, but I think this code is dealing with bytes. The correct thing to do is probably to change PChar to PByte, and then you don't need to type-cast Dest at all.
The $J directive is irrelevant; it controls whether the compiler will allow you to assign values to typed constants. You don't have any of those in this code.
The reason is that as of Delphi 2009, Char, PChar, and String are Unicode, and store more than one byte per character.
You should not cast those pointers to bytes, and the compiler prevents you from assigning them if you cast the left side of an assignment to a byte.
This compiles:
procedure CopyInterlacedRGB8(const Pass: Byte; Dest: pAnsiChar); overload;
begin
Byte(Dest^) := Pass;
end;
This doesn't:
procedure CopyInterlacedRGB8(const Pass: Byte; Dest: pChar); overload;
begin
Byte(Dest^) := Pass;
end;
Instead of pChar, you should use pByte, which makes the code simpler:
procedure CopyInterlacedRGB8(const Pass: Byte; Dest: PByte); overload;
begin
Dest^ := Pass;
end;
--jeroen
That looks like you're working with Gustavo Daud's TPngImage library. You don't need that code in an external BPL because it's been included in the RTL since D2009. Remove that unit from the BPL and you should be able to get at the updated version via the PngImage unit.

How to use a TFileStream to read 2D matrices into dynamic array?

I need to read a large (2000x2000) matrix of binary data from a file into a dynamic array with Delphi 2010. I don't know the dimensions until run-time.
I've never read raw data like this, and don't know IEEE so I'm posting this to see if I'm on track.
I plan to use a TFileStream to read one row at a time.
I need to be able to read as many of these formats as possible:
16-bit two's complement binary integer
32-bit two's complement binary integer
64-bit two's complement binary integer
IEEE single precision floating-point
For 32-bit two's complement, I'm thinking something like the code below. Changing to Int64 and Int16 should be straight forward. How can I read the IEEE?
Am I on the right track? Any suggestions on this code, or how to elegantly extend it for all 4 data types above? Since my post-processing will be the same after reading this data, I guess I'll have to copy the matrix into a common format when done.
I have no problem just having four procedures (one for each data type) like the one below, but perhaps there's an elegant way to use RTTI or buffers and then move()'s so that the same code works for all 4 datatypes?
Thanks!
type
TRowData = array of Int32;
procedure ReadMatrix;
var
Matrix: array of TRowData;
NumberOfRows: Cardinal;
NumberOfCols: Cardinal;
CurRow: Integer;
begin
NumberOfRows := 20; // not known until run time
NumberOfCols := 100; // not known until run time
SetLength(Matrix, NumberOfRows);
for CurRow := 0 to NumberOfRows do
begin
SetLength(Matrix[CurRow], NumberOfCols);
FileStream.ReadBuffer(Matrix[CurRow], NumberOfCols * SizeOf(Int32)) );
end;
end;
No, AFAIK there's no way to use RTTI to set up multidimensional arrays. But if you're using Delphi 2010, you should be able to use generics, like so:
type
TRowData<T> = array of T;
procedure ReadMatrix<T>;
var
Matrix: array of TRowData<T>;
NumberOfRows: Cardinal;
NumberOfCols: Cardinal;
CurRow: Integer;
begin
NumberOfRows := 20; // not known until run time
NumberOfCols := 100; // not known until run time
SetLength(Matrix, NumberOfRows, NumberOfCols);
for CurRow := 0 to NumberOfRows do
FileStream.ReadBuffer(Matrix[CurRow][0], NumberOfCols * SizeOf(T)) );
end;
This will have to be in a class, though, as Delphi 2010 doesn't support standalone procedures with generic types. Once you've got this set up, you can call TWhateverClass.ReadMatrix<integer>, TWhateverClass.ReadMatrix<int64>, TWhateverClass.ReadMatrix<single>, and so on.
Also, if you have a multidimensional array with X dimensions, you can pass X length parameters to SetLength, not just one. So use one call to SetLength(Matrix, NumberOfRows, NumberOfCols) outside the loop, instead of initializing each row separately to the same width.

Delphi Array Alignment set to 4, 8, or 16 byte boundaries?

I would like to use the FFTW C library from Delphi 2009 and according to this documentation;
http://www.fftw.org/install/fftw_usage_from_delphi.txt
to increase the performance inside the FFTW library (such that it can use SIMD extensions) arrays passed in of either Single (float) or Double (double) need to be aligned either at 4 or 8 byte boundaries. I found documentation talking about alignment of record structures, but nothing specific about arrays. Is there a way to do this in Delphi 2009.
So the code (copied from the above documentation) would look like this;
var
in, out : Array of Single; // Array aligned at 4 byte boundary
plan : Pointer;
{$APPTYPE CONSOLE}
begin
...
SetLength(in, N);
SetLength(out, N);
plan := _fftwf_plan_dft_1d(dataLength, #in[0], #out[0],
FFTW_FORWARD, FFTW_ESTIMATE);
Also in the above documentation they talk about 8 and 16 byte boundaries but it looks to me it should be 4 and 8 byte boundaries, if any could clear that up to that would be great.
Thanks,
Bruce
Note that you can create data structures with any custom alignment you might need. For example to align your FFT data on 128 byte boundaries:
procedure TForm1.Button1Click(Sender: TObject);
type
TFFTData = array[0..63535] of double;
PFFTData = ^TFFTData;
var
Buffer: pointer;
FFTDataPtr: PFFTData;
i: integer;
const
Alignment = 128; // needs to be power of 2
begin
GetMem(Buffer, SizeOf(TFFTData) + Alignment);
try
FFTDataPtr := PFFTData((LongWord(Buffer) + Alignment - 1)
and not (Alignment - 1));
// use data...
for i := Low(TFFTData) to High(TFFTData) do
FFTDataPtr[i] := i * pi;
finally
FreeMem(Buffer);
end;
end;
Edit:
Regarding the comment about twice the memory being allocated: The stack variable FFTData is of type PFFTData, not of TFFTData, so it's a pointer. It's not that obvious because of the syntax enhancement allowing to omit the ^ for dereferencing the pointer. The memory is allocated with GetMem(), and to work with the proper type instead of the untyped memory block the typecast is employed. I should probably have called it FFTDataPtr.
Delphi provides no way to control the alignment of any memory it allocates. You're left to either rely on the documented behavior for the memory manager currently installed, or allocate memory with some slack space and then align it yourself, as Mghie demonstrates.
If you're concerned that Delphi's memory manager is not providing the desired alignment for dynamic arrays, then you can go ahead and use the memory functions provided by the DLL. The note you cite mentions _fftwf_malloc and _fftwf_free, but then it gives some kind of warning that memory allocated from _fftwf_malloc "may not be accessed directly from Delphi." That can't be what the authors meant to say, though, because that's not how memory works in Windows. The authors probably meant to say that memory allocated by _fftwf_malloc cannot be freed by Delphi's FreeMem, and memory allocated by Delphi's GetMem cannot be freed by _fftwf_free. That's nothing special, though; you always need to keep your memory-management functions paired together.
If you use _fftwf_malloc to get your array, then you can access it through an ordinary pointer type. For example:
var
dataIn, dataOut: PDouble;
begin
dataIn := _fftwf_malloc(...);
dataOut := _fftwf_malloc(...);
_fftwf_plan_dft_1d(dataLength, dataIn, dataOut,
FFTW_FORWARD, FFTW_ESTIMATE);
As of Delphi 2009, you can even use array syntax on those pointers:
dataIn[0] := 3.5;
dataIn[2] := 7.3;
In order to enable that, use the {$POINTERMATH ON} compiler directive; it's not enabled by default except for the character-pointer types.
The disadvantage to manually allocating arrays like this is that you lose range checking. If you index beyond the end of an array, you won't get an easy-to-recognize ERangeError exception anymore. You'll get corrupted memory, access violations, or mysteriously crashing programs instead.
Heap blocks are iirc always aligned to 16-byte bounderies by FastMM (the old D7 memmanager aligned to 8). I don't know about sharemem, since I don't use it.
And dynamic arrays are heap based structures. OTOH dyn arrays could maybe become unaligned (from 16 to 8) because there is a length and ref count prefixed. Easiest is to simply print
ptruint(#in[0]) in hex and see if the end is 0 or 8. (*)
Note that there are fftw headers in FPC. ( packages/fftw), afaik it was recently fixed for 64-bit even.
I'm not aware of Stack alignment directives in Delphi. Maybe they are automatically "naturally" aligned though.
(*) ptruint is FPC speak for an unsigned integer type that is sizeof(pointer) large. cardinal on 32-bit, qword on 64-bit.
This is another possible variant of mghie's solution:
procedure TForm1.Button1Click(Sender: TObject);
type
TFFTData = array [0..0] of Double;
PFFTData = ^TFFTData;
var
AllocatedBuffer: Pointer;
AlignedArray: PFFTData;
i: Integer;
const
cFFTDataSize=63536;
begin
GetMem(AllocatedBuffer, cFFTDataSize*SizeOf(Double) + 16); // e.g 16 Bytes boudaries alignement
try
AlignedArray := PFFTData((Integer(AllocatedBuffer) and $FFFFFFF0) + 16);
// use data...
for i := 0 to cFFTDataSize-1 do
AlignedArray[i] := i * Pi;
finally
FreeMem(AllocatedBuffer);
end;
end;
I've refactored the piece of code to make it more meaningfull and make use of a similar manual alignement fix up technique.

Resources