Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2019-11

Why is setlength not allowed?

5 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bo Berglund

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

Reply by email

Michael Van Canneyt
to Bo Berglund
Bo Berglund wrote 26 lines
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.

Reply by email

Bo Berglund
to Michael Van Canneyt
Michael Van Canneyt wrote 59 lines
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

Reply by email

Michael Van Canneyt
to Bo Berglund
Bo Berglund wrote 28 lines
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.

Reply by email

Bo Berglund
to Michael Van Canneyt
Michael Van Canneyt wrote 6 lines
> 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

Reply by email