Continuing from the topic here, being unfamiliar with pointers,
how to correctly call the function bellow, given the fact that the pointers in it are the data to be retrieved back, and how to actually get to that data after calling it?
function RetrieveDSOData(whatchannels: Byte; DSOCH1, DSOCH2: PDouble; LADATA: PWord; Nth_Sample: Byte): longint; cdecl; external 'E_l80.dll';
(Needed DSOCH1, DSOCH2 and LADATA data...)
If it's in any help / important at all -> the documentation states that these are "pointers to an array".
In case this is a duplicate and I just didn't look by correct keywords, vote for closing this.
Thank you.
Edit:
It is to be assumed the size can be received by the return of the function. Documentation states:
Return: The number of samples in the DSO and LA arrays. This number may not
be (total blocks x 1024) as some samples at the beginning and end are thrown away for
various purposes.
So, max size might be (1024 x 32samples x 2 (2x8 digital channels, 2 bytes?)) for LADATA array...
You have to call the function with addresses of arrays, and it will fill these arrays. Example:
var
DS1: array[0..31] of Double;
RetrieveDSOData(whatchannels, #DS[0], ...
Related
Given the following:
LBytes: TBytes;
LArr: array[1..512] of Byte;
...
SetLength(LBytes, 512);
What is the correct Move() call to copy all bytes from LBytes to LArr?
Move(LBytes[0], LArr, Length(LBytes)); // works
Move(LBytes[0], LArr[1], Length(LBytes)); // works, too
Move(LBytes, LArr[1], Length(LBytes)); // fail
Can someone explain why it makes no difference between using Larr and Larr[1] but makes a difference between LBytes[0] and LBytes?
Can someone explain why it makes no difference between using Larr and Larr1 but makes a difference between LBytes[0] and LBytes?
That's because LBytes is a dynamic array which is, ultimately, a pointer to the array. On the other hand, LArr is the array.
Another way to say this is that dynamic arrays are reference types, and fixed length arrays are value types.
In my book, there are two viable ways to do this:
Assert(Length(LBytes)<=Length(LArr));
Move(LBytes[0], LArr, Length(LBytes));
or
Assert(Length(LBytes)<=Length(LArr));
Move(Pointer(LBytes)^, LArr, Length(LBytes));
I prefer the latter, because it is resilient to a zero length array when range checking is enabled. In that scenario, the first block of code leads to a run time range check error.
You might also be motivated to avoid such low-level trickery. I have a utility class that allows me to write:
TArray.Move<Byte>(LBytes, LArr);
The signature of the method is:
class procedure Move<T>(const Source: array of T; var Dest: array of T); overload; static;
I am Delphi 6 developer. And trying to call C++ dll function from delphi.
Dll written in C++ and the have Char pointer as out parameter.
Eg.
Function doGetStatus(Var szStatusData : Char) : Integer; cdecl; external 'WhizCal.dll';
When I call function from DLL I send char variable 'szStatusData' and return value should be 'Down' or 'Live' but it retuens only 'D' or 'L' this is because I have passed Char variable reference.
My question is, what can I do for getting return data as 'Down' or 'Live' without changing datatype.
A char is just a single character. So you cannot expect more.
Most likely the C++ code expects to be passed a pointer to an array of characters. Perhaps it should be like this:
function doGetStatus(szStatusData: PAnsiChar): Integer; cdecl; external 'WhizCal.dll';
And you might call it like this:
var
StatusData: array [0..255] of AnsiChar;
RetVal: Integer;
....
RetVal := doGetStatus(StatusData);
// check RetVal
We cannot tell you what exactly your code should be because we don't have any details of the specified interface. Unless the caller also passes the length of the array, such a function is bait for buffer overrun errors. As written above, this is the case. How can the caller know how much space to allocate. Well designed functions also allow the caller to pass the length of the array that they supplied.
My general advice to you is that interop is a topic that demands precision and detail, and knowledge of both sides of the boundary. You need to find out that detail.
I'm trying to do filtering .wav sample data value using the HAAR formula but got error "floating point overflow"
Edited : add more code
numsamples := round(wavehdr.SampleRate);
SetLength(wavedata[0].Data, numsamples);
Stream.Read(wavedata[0].Data[0], numsamples);
SetLength(cA1, numsamples);
SetLength(cD1, numsamples);
for i:=1 to numsamples-1 do begin
cA1[i]:=(wavedata[0].Data[(i*2)-1]*0.7071) + (wavedata[0].Data[(i*2)]*0.7071);
cD1[i]:=(wavedata[0].Data[(i*2)-1]*0.7071) + (wavedata[0].Data[(i*2)]*-0.7071);
end;
where wavedata[0].Data[i], i get it from function Stream.Read to load sample data value of .wav file. I don't know why i got the error or what the error means and i've been searching the error mostly caused of divizion by zero, but there is no divizion by zero in my code. So maybe i could some help here what is the error mean in my code?
EDIT 1: (i'm really new to delphi, this code is not mine i found it internet. In my understanding the following code is the one to read .wav file sample data value)
type
TWaveHeader = packed record
Marker_RIFF: array [0..3] of char;
ChunkSize: cardinal;
Marker_WAVE: array [0..3] of char;
Marker_fmt: array [0..3] of char;
SubChunkSize: cardinal;
FormatTag: word;
{ nChannels : 1 mono, 2 stereo }
NumChannels: word;
SampleRate: longint;
BytesPerSecond: longint;
BytesPerSample: word;
BitsPerSample: word;
Marker_data: array [0..3] of char;
DataBytes: longint;
end;
TChannel = record
Data : array of double;
end;
And a private declaration :
private
wavehdr:TWaveHeader;
the function :
FillChar(wavehdr, sizeof(wavehdr),0);
Stream.Read(wavehdr,sizeof(wavehdr));
i modified a bit of the code to handle null value while reading the sample data :
if(IsNan(wavedata[0].Data[(i*2)-1])) then begin
wavedata[0].Data[(i*2)-1]:=0;
end
else if(IsNan(wavedata[0].Data[(i*2)])) then begin
wavedata[0].Data[(i*2)]:=0;
end;
for i:=0 ...
(wavedata[0].Data[(i*2)-1]
Do you really have array element Data[-1] ?
P.S. Set range check compiler option while debugging.
Edit: I see some new code, so let's go with step 2:
SetLength(wavedata[0].Data, **numsamples**);
for i:=1 to **numsamples**-1
wavedata[0].Data[(**i*2)**]
Have we to check thoroughly every line of code?
Overflow occurs when an expression yields a value that does not fit in the range of the data type in which the expression is evaluated. Overflow can occur for positive and negative numbers.
Your particular expression will only result in overflow if the input values are already close to overflowing a floating point value. So, if you are using double precision values for example, then your code can only overflow if the input data has magnitude of around 1e308.
It seems unlikely that your input data is really of that form. So my guess is that your problem is related to how you read your input data. I suspect you are reading it incorrectly and so end up performing arithmetic on meaningless values.
After i try this and that i figured out my own mistakes, thanks to #MBo your answer narrowing mw focus in the loop, it's really stupid of me. The looping should be like
for i:=0 to round(numsamples/2) do begin
it is not element Data[-1] that the problem but, if length of array wavedata = X, then i try to reach the element of [X*2] which are not available it's surely after a half will cause an error. eg array[4] but i try to reach array[4*2] which is not available (Sorry for my bad english, i dont know if my explanation was good or not) but thanks everyone for the help :D
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.
I'm developing class to represent special kind of matrix:
type
DifRecord = record
Field: String;
Number: Byte;
Value: smallint;
end;
type
TData = array of array of MainModule.DataRecord;
type
TDifference = array of DifRecord;
type
TFogelMatrix = class
private
M: Byte;
N: Byte;
Data: ^TData;
DifVector: ^TDifference;
procedure init();
public
constructor Create(Rows, Cols: Byte);
destructor Destroy;
end;
Now in constructor I need to reserve memory for Data and DifVector class members. I use pointers to array of records, as you see. So, the main question is, how can I correctly reserve memory? I suppose I can not use something like that:
new(Data);
new(DifVector);
cause I`m loosing the main idea - to reserve memory space, as much as I want to, at run-time. Thanks for comments.
Since you're using dynamic arrays, array of, then you should use SetLength to specify the length of the array, which can be done dynamically.
ie. like this:
SetLength(Data, 100);
This will not reserve 100 bytes, but will reserve enough space to hold 100 elements of whatever type the array holds.
Change your declarations for the arrays to simple arrays:
Data: TData;
DifVector: TDifference;
and use it with SetLength, it should do the trick.
Also note that In Delphi variables of a dynamic array type are stored as a pointer (in DotNet-speak you would call this a reference-type).
Unless you cast this variable to a pointer, the compiler won't let you do the allocation yourself. You should use SetLength() like lassevk mentioned already.
With a multi-dimensional array (like TData), you could set both dimensions in one go, by setting all dimension with one call to SetLength(). This results in a cube-like structure (each dimension has equal length). But it's also possible to give each index within a dimension a different length to it's next dimension. With two dimensions, this is sometimes called a 'jagged' array.
To do this, you would write it out like this :
SetLength(Data, SizeOfFirstDimension);
for i = 0 to SizeOfFirstDimension - 1 do
SetLength(Data[i], SizeOfSecondDimensionPerIndex(i));
In this example, I use a function called 'SizeOfSecondDimensionPerIndex' to determine the size of each array in the 2nd dimension, but you could determine this size any way you want.
On a side-note, I would advise you to use the 'R'-prefix for record-type definitions. I know this not in any of the major coding-style guides, but if you look at 'P'-prefixes for pointers, 'I'-prefixes for interfaces, 'F'-prefixes for class-fields, 'a'-prefixes for arguments, 'C'-prefixes for constants, 'S'-prefixes for resourcestring's, you can follow this logic and use an 'R'-prefix for records. I know this has helped me to get a better grasp of my code!
Good luck!