Discussion:
[D7 + Indy 9 -> 10] TBytes vs. TIdBytes
(too old to reply)
Vincent Delporte
2006-07-12 13:10:19 UTC
Permalink
Hello

I'm stuck with an error after upgrading from Indy 9 to Indy
10. Browsing the archives didn't solve this issue that other
encountered, so here it goes...

1. I followed the instructions in the KB "How do I install Indy into
Borland Delphi?" to uninstall Indy 9, and then ran Indy Install Plus
to install Indy 10.1.5. It worked OK as far as I can tell.

Next, I added a UDPServer widget in the form, and added some dummy
code for the OnUDPRead event:

-------- CODE----------
procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TByte;
ABinding: TIdSocketHandle);
begin

ShowMessage('incoming');

end;
-------- CODE----------

=> In the Type section, on the line "procedure IdUDPServer1UDPRead",
Delphi shows error "[Error] Unit1.pas(15): Undeclared identifier:
'TBytes'".

2. The archives of this ng say that it's apparently a bug in Delphi,
and that I should try changing all occurences of TBytes to TIdBytes,
add IdGlobal and IdSocketHandle to the uses clause, and hit F9.

=> "Error/The IdUDPServer1UDPRead method referenced by
IdUDPServer1.OnUDPRead has an incompatible parameter list. Remove the
reference?"

Leaving IdGlobal and IdSocketHandle in the uses clause while changing
TIdBytes back to TBytes let me run the program, and respond to
incoming UDP packets.

3. However, when changing the even trigger code to this:

-------- CODE----------
procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TBytes;
ABinding: TIdSocketHandle);
var
LMsg: string;
begin
SetLength(LMsg, AData.Size);
AData.ReadBuffer(LMsg[1], Length(LMsg));
Label1.Caption := TimeToStr(Time) + ' : ' + LMsg;
end;
-------- CODE----------

=> "SetLength(LMsg, AData.Size);" :
[Error] Unit1.pas(42): Record, object or class type required

So, I'm still stuck with TBytes and TIdBytes. Any idea?

Thank you.
Remy Lebeau (TeamB)
2006-07-12 17:28:19 UTC
Permalink
I'm stuck with an error after upgrading from Indy 9 to Indy 10.
It is a Delphi bug, not an Indy error. Delphi is not generating the event
handler signature properly. You will have to update the code by hand
accordingly to make it work. You need to add IdGlobal to the uses clause,
and change the event handler to use TIdBytes instead of TBytes.
The archives of this ng say that it's apparently a bug in Delphi, and
that I should try changing all occurences of TBytes to TIdBytes, add
IdGlobal and IdSocketHandle to the uses clause, and hit F9.
That is correct.
[Error] Unit1.pas(42): Record, object or class type required
TBytes is an array of Bytes. It does not have a Size property (or any
properties, for that matter). You need to use Length() instead, ie:

SetLength(LMsg, Length(AData));
AData.ReadBuffer(LMsg[1], Length(LMsg));
AData does not have any methods, either. It looks like you are trying to
use old Indy 9 code with an Indy 10 event handler. You are trying to treat
the TBytes like a TStream, which it is not. Since it is just an array, you
will have to copy its contents directly, ie:

Move(Data[0], LMsg[1], Length(AData));

With that said, the IdGlobal unit has a BytesToString() function that you
can use instead, ie:

procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TBytes;
ABinding: TIdSocketHandle);
begin
Label1.Caption := TimeToStr(Time) + ' : ' + BytesToString(AData);
end;


Gambit
Vincent Delporte
2006-07-12 21:07:40 UTC
Permalink
On Wed, 12 Jul 2006 10:28:19 -0700, "Remy Lebeau \(TeamB\)"
Post by Remy Lebeau (TeamB)
It looks like you are trying to
use old Indy 9 code with an Indy 10 event handler.
Indeed, I googled for this code, but the author didn't specify which
version of Indy it was for. Obviously, it was for Indy 9, hence the
errors after upgrading to Indy 10. Thanks for your help, it's working
now.

For those interested, here's a sample:

uses
[...], IdUDPServer,IdGlobal,IdSocketHandle;

procedure TForm1.FormActivate(Sender: TObject);
begin
IdUDPServer1.DefaultPort := 4567;
IdUDPServer1.Active := True;
end;

procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TBytes;
ABinding: TIdSocketHandle);
var
LMsg: string;
begin
if Length(AData) = 0 then begin
Label1.Caption := TimeToStr(Time) + ' : Empty packet';
end else begin
Label1.Caption := TimeToStr(Time) + ' : ' + BytesToString(AData);
end;
end;

Loading...