[Lazarus] Why is setlength not allowed?

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[Lazarus] Why is setlength not allowed?

Free Pascal - Lazarus mailing list
I am trying to write a simple I2C interface program for Raspberry Pi
but I am getting an error I don't understand...

function TRaspiI2C.ReadI2CBytes(addr: integer; count: integer; buf:
array of byte): integer;
var
  i: integer;
begin
  try
    if count <> length(buf) then
      SetLength (buf, count);  <== ERROR HERE!
    for i := 0 to count -1 do
      buf[i] := ReadI2CByte(addr + i);
    Result := count;
  except
    Result := 0;
  end;
end;

The error message states:

rpii2ccomm.pas(158,7) Error: Type mismatch

I have used setlength on dynamic byte arrays many times before and
never gotten this strange error message.
What am I doing wrong???

I have tried declaring buf as var in the call but it does not help.

(addr: integer; count: integer; var buf: array of byte): integer;

The same error happens.

Must be something basic I have missed.

Lazarus placed this at the top of the unit when I created it, if that
matters:

{$mode objfpc}{$H+}

Using FPC 3.0.4 and Lazarus 2.0.6 on Raspbian Buster


--
Bo Berglund
Developer in Sweden

--
_______________________________________________
lazarus mailing list
[hidden email]
https://lists.lazarus-ide.org/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Why is setlength not allowed?

Free Pascal - Lazarus mailing list


On Sat, 16 Nov 2019, Bo Berglund via lazarus wrote:

> I am trying to write a simple I2C interface program for Raspberry Pi
> but I am getting an error I don't understand...
>
> function TRaspiI2C.ReadI2CBytes(addr: integer; count: integer; buf:
> array of byte): integer;
> var
>  i: integer;
> begin
>  try
>    if count <> length(buf) then
>      SetLength (buf, count);  <== ERROR HERE!
>    for i := 0 to count -1 do
>      buf[i] := ReadI2CByte(addr + i);
>    Result := count;
>  except
>    Result := 0;
>  end;
> end;
>
> The error message states:
>
> rpii2ccomm.pas(158,7) Error: Type mismatch
>
> I have used setlength on dynamic byte arrays many times before and
> never gotten this strange error message.
> What am I doing wrong???

Because buf is not a dynamic array, but an open array.

"Open array" predates dynamic arrays, and served to be able to pass
fixed-lengh arrays of different lengths to a single function, so you would
not have to declare the same function for all array lengths.

function TRaspiI2C.ReadI2CBytes(addr: integer; count: integer; buf:  array of byte): integer;

Means you can do
type
   T10BytesArray = Array[1..10];
   T100BytesArray = Array[1..100];

var
   A10 : T10BytesArray;
   A100 : T100BytesArray;

begin
   ReadI2CBytes(1,10,A10);
   ReadI2CBytes(1,100,A100);
end;

What you need is:

  TByteArray = Array of Byte;

  function TRaspiI2C.ReadI2CBytes(addr: integer; count: integer; var buf: TByteArray): integer;


Michael.
--
_______________________________________________
lazarus mailing list
[hidden email]
https://lists.lazarus-ide.org/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Why is setlength not allowed?

Free Pascal - Lazarus mailing list
On Sat, 16 Nov 2019 09:20:28 +0100 (CET), Michael Van Canneyt via
lazarus <[hidden email]> wrote:

>
>
>On Sat, 16 Nov 2019, Bo Berglund via lazarus wrote:
>
>> I am trying to write a simple I2C interface program for Raspberry Pi
>> but I am getting an error I don't understand...
>>
>> function TRaspiI2C.ReadI2CBytes(addr: integer; count: integer; buf:
>> array of byte): integer;
>> var
>>  i: integer;
>> begin
>>  try
>>    if count <> length(buf) then
>>      SetLength (buf, count);  <== ERROR HERE!
>>    for i := 0 to count -1 do
>>      buf[i] := ReadI2CByte(addr + i);
>>    Result := count;
>>  except
>>    Result := 0;
>>  end;
>> end;
>>
>> The error message states:
>>
>> rpii2ccomm.pas(158,7) Error: Type mismatch
>>
>> I have used setlength on dynamic byte arrays many times before and
>> never gotten this strange error message.
>> What am I doing wrong???
>
>Because buf is not a dynamic array, but an open array.
>
>"Open array" predates dynamic arrays, and served to be able to pass
>fixed-lengh arrays of different lengths to a single function, so you would
>not have to declare the same function for all array lengths.
>
>function TRaspiI2C.ReadI2CBytes(addr: integer; count: integer; buf:  array of byte): integer;
>
>Means you can do
>type
>   T10BytesArray = Array[1..10];
>   T100BytesArray = Array[1..100];
>
>var
>   A10 : T10BytesArray;
>   A100 : T100BytesArray;
>
>begin
>   ReadI2CBytes(1,10,A10);
>   ReadI2CBytes(1,100,A100);
>end;
>
>What you need is:
>
>  TByteArray = Array of Byte;
>
>  function TRaspiI2C.ReadI2CBytes(addr: integer; count: integer; var buf: TByteArray): integer;
>

Thanks so much! Now working.

But I have another issue, a warning from the compiler:

function InitI2cDevice(devpath: String; iDevAddr: Cint; var hInst:
Integer): Integer;
var
  iio : integer;
begin
  try
    hInst := fpopen(devpath, O_RDWR);                       //Open the
I2C bus in Read/Write mode
    iio := FpIOCtl(hInst, I2C_SLAVE, Pointer(iDevAddr));    //Set
options
    if (iio = 0) and (hInst > 0) then
      Result := hInst
    else
      Result := -1;
  except
    Result := -1;
  end;
end;

In this case I get a warning:
rpii2ccomm.pas(80,38) Hint: Conversion between ordinals and pointers
is not portable

It is on the line:
iio := FpIOCtl(hInst, I2C_SLAVE, Pointer(iDevAddr));

I guess that the reason is that fpIoCtrl expects a pointer type
variable so the typecast is done... Is there no alternative?

(As you might suspect I am trying to adapt code found on the Internet
in my unit for I2C communication....)


--
Bo Berglund
Developer in Sweden

--
_______________________________________________
lazarus mailing list
[hidden email]
https://lists.lazarus-ide.org/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Why is setlength not allowed?

Free Pascal - Lazarus mailing list


On Sat, 16 Nov 2019, Bo Berglund via lazarus wrote:

> function InitI2cDevice(devpath: String; iDevAddr: Cint; var hInst:
> Integer): Integer;
> var
>  iio : integer;
> begin
>  try
>    hInst := fpopen(devpath, O_RDWR);                       //Open the
> I2C bus in Read/Write mode
>    iio := FpIOCtl(hInst, I2C_SLAVE, Pointer(iDevAddr));    //Set
> options
>    if (iio = 0) and (hInst > 0) then
>      Result := hInst
>    else
>      Result := -1;
>  except
>    Result := -1;
>  end;
> end;
>
> In this case I get a warning:
> rpii2ccomm.pas(80,38) Hint: Conversion between ordinals and pointers
> is not portable
>
> It is on the line:
> iio := FpIOCtl(hInst, I2C_SLAVE, Pointer(iDevAddr));
>
> I guess that the reason is that fpIoCtrl expects a pointer type
> variable so the typecast is done... Is there no alternative?

The warning seems correct. I suspect Pointer(iDevAddr) is probably wrong.
Maybe  Pointer(@iDevAddr)) is needed. I would need to see the original code.

Michael.
--
_______________________________________________
lazarus mailing list
[hidden email]
https://lists.lazarus-ide.org/listinfo/lazarus
Reply | Threaded
Open this post in threaded view
|

Re: [Lazarus] Why is setlength not allowed?

Free Pascal - Lazarus mailing list
On Sat, 16 Nov 2019 11:50:45 +0100 (CET), Michael Van Canneyt via
lazarus <[hidden email]> wrote:

>> I guess that the reason is that fpIoCtrl expects a pointer type
>> variable so the typecast is done... Is there no alternative?
>
>The warning seems correct. I suspect Pointer(iDevAddr) is probably wrong.
>Maybe  Pointer(@iDevAddr)) is needed. I would need to see the original code.
>

I created my code by studying this on github:
https://github.com/tmssoftware/TMS-LCL-HW-Pack-for-Raspberry-Pi/blob/master/tmslclraspihw.pas

The "pointer" is on line 143

In any case it seems like it is working right now in real life. I can
read and write the i2c EEPROM device on my Raspberry Pi4.

And if the warning relates to porting this code to other platforms it
does not matter since it is destined for the RPi hardware and will not
be ported...


--
Bo Berglund
Developer in Sweden

--
_______________________________________________
lazarus mailing list
[hidden email]
https://lists.lazarus-ide.org/listinfo/lazarus