I have to interact with an external device through a DLL. In order to map arrays from C to BBoxCP I have to use the modifier "untagged" while declaring an array type on the CP part. One of the restrictions of the BBox
is that I cannot allocate such arrays dynamically (using NEW). The HW provides multiple data buffers with different lengths, and depends on my configuration at run-time, I would like to read my measurements out of one of these buffers.
This is my attempt to solve it using a pointer to an array of a certain type and assign an address of one of the buffers at run-time. A simplified version of the program is presented below:
Code: Select all
MODULE dmTestArrPtr;
IMPORT Log := StdLog, S:=SYSTEM;
CONST
MSize = 5;
TYPE tSArr1 = ARRAY MSize OF REAL;
tSArr2 = ARRAY 2 * MSize OF REAL;
oPtrArr = POINTER TO ARRAY OF REAL;
VAR
StArr10 : tSArr1;
StArr20 :tSArr2;
PtrArr: oPtrArr;
i : INTEGER;
PROCEDURE Run*;
BEGIN
(* get an address of the array StArr10 and make a pointer of out it *)
Log.String("Arrays after modification .."); Log.Ln();
PtrArr := S.VAL(oPtrArr, S.ADR(StArr10));
FOR i := 0 TO LEN(StArr10) -1 DO
PtrArr[i] := 2.0 * PtrArr[i] ;
END;
PtrArr := S.VAL(oPtrArr, S.ADR(StArr20));
FOR i := 0 TO LEN(StArr20) -1 DO
PtrArr[i] := 0.5 * PtrArr [i] ;
END;
FOR i := 0 TO LEN(StArr10) -1 DO
Log.String("Modified Arr10=");Log.Real(StArr10[i]); Log.Ln();
END;
Log.String("_______________xxx_____________"); Log.Ln();
FOR i := 0 TO LEN(StArr20) -1 DO
Log.String("Modified Arr20=");Log.Real(StArr20[i]); Log.Ln();
END;
Log.String("_______________xxx_____________"); Log.Ln();
Log.String("_______________xxx_____________"); Log.Ln();
END Run;
BEGIN
Log.String("_______________________________"); Log.Ln();
Log.String("_______________________________"); Log.Ln();
Log.String("Arrays before modification .."); Log.Ln();
(* initialise StArr10 *)
FOR i := 0 TO LEN(StArr10) -1 DO
StArr10[i] := 1.0 + i;
Log.String("Arr10=");Log.Real(StArr10[i]); Log.Ln();
END;
Log.String("_______________________________"); Log.Ln();
(* initialise StArr20 *)
FOR i := 0 TO LEN(StArr20) -1 DO
StArr20[i] := 2 * ( i + 1);
Log.String("Arr20=");Log.Real(StArr20[i]); Log.Ln();
END;
Log.String("_______________________________"); Log.Ln();
Log.String("_______________________________"); Log.Ln();
END dmTestArrPtr.
dmTestArrPtr.Run
DevDebug.UnloadThis dmTestArrPtr
_______________________________
_______________________________
Arrays before modification ..
Arr10= 1.0
Arr10= 2.0
Arr10= 3.0
Arr10= 4.0
Arr10= 5.0
_______________________________
Arr20= 2.0
Arr20= 4.0
Arr20= 6.0
Arr20= 8.0
Arr20= 10.0
Arr20= 12.0
Arr20= 14.0
Arr20= 16.0
Arr20= 18.0
Arr20= 20.0
_______________________________
_______________________________
Arrays after modification ..
Modified Arr10= 0.5
Modified Arr10= 1.0
Modified Arr10= 6.0
Modified Arr10= 8.0
Modified Arr10= 10.0
_______________xxx_____________
Modified Arr20= 2.0
Modified Arr20= 4.0
Modified Arr20= 3.0
Modified Arr20= 4.0
Modified Arr20= 5.0
Modified Arr20= 6.0
Modified Arr20= 7.0
Modified Arr20= 8.0
Modified Arr20= 9.0
Modified Arr20= 10.0
_______________xxx_____________
_______________xxx_____________
In the StArr10 each element is multiply by 2, and in the StArr20 each element is divided by 2. First two elements of StArr10 and StArr20 have wrong values!!
So, my question is:
How I should implement such a feature correctly?
There is a warning saying:
and I have experienced (hard way) when the result of VAL has been assigned to a BBox pointer.VAL, PUT, PUTREG, and MOVE may crash BlackBox and/or Windows when not used properly.
Never use VAL (or PUT or MOVE) to assign a value to a BlackBox pointer. Doing this would corrupt the garbage collector, with fatal consequences.
Cheers,
Darek
P.S. I am using BBox CP version 1.6.