how do I use setstate (lnet)? - freepascal

When I use setstate I always get this error: unit1.pas(34,49) Error: Only class methods, class properties and class variables can be referred with class references, why does this error occur? I think the error lays in ssNoDelay, as without it the before mentioned error doesn't happen.
I made this empty project as an example:
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, lNetComponents, lNet;
type
{ TForm1 }
TForm1 = class(TForm)
LTCPComponent1: TLTCPComponent;
procedure FormCreate(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
LTCPComponent1.SocketClass.SetState(ssNoDelay);
end;
end.

SetState has to be used on a TLSocket, not on the TLCTPComponent. This means you can only use SetState when you already have a connection you want to apply one of the options (ssNoDelay for example) on (so the best solution is to use setstate in the OnAccept / OnConnect procedure if you want to use an option from the start).

Related

Delphi - why does this function work if the class is not created?

Consider this class:
unit Unit2;
interface
type
TTeste = class
private
texto: string;
public
function soma(a, b: integer): string;
end;
implementation
procedure TForm2.Button1Click(Sender: TObject);
var
teste: TTeste;
begin
teste:= nil;
teste.texto:= '';//access violation
showmessage(teste.soma(5, 3));//no access violation
end;
{ TTeste }
function TTeste.soma(a, b: integer): string;
begin
result:= (a+b).ToString;
end;
end.
should it really work? why? the var crashed but the function doesnt, does it works like a class funtion?
This works because you are not attempting to access any fields of the class. The function doesn't require any memory allocation. If the field texto was used in that function, then it would crash (as you see in your other test), because that memory isn't addressed. But here, there is no memory involved. Both a and b (and the function result for that matter) are allocated elsewhere outside of the class. Part of the instantiation process is allocating memory for each and every one of the fields in the object.
This is just coincidental. It's still highly discouraged to actually use something like this. If you feel the need to access the function without instantiation, then you should make it a class function instead.

Delphi: Undeclared Identifier in Procedure

I want to edit a property of a shape inside a procedure.
However if I create my own procedure I get an "undefinded identifier" error.
I tried to edit the property in the OnCreate event procedure of my form and that works just fine.
Why is it like that and how can I fix it?
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;
type
Tfrm_main = class(TForm)
shp_wheelLeftInside: TShape;
shp_wheelRightInside: TShape;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frm_main: Tfrm_main;
implementation
{$R *.dfm}
procedure addWheelInsides();
begin
shp_wheelRightInside.Height := 42; //this is where the error occurs
end;
procedure Tfrm_main.FormCreate(Sender: TObject);
begin
shp_wheelLeftInside.Height := 42;
shp_wheelRightInside.Height := 42;
addWheelInsides();
end;
end.
The problem is that shp_wheelRightInside is a field that belongs to your Tfrm_main class whereas the addWheelInsides() method you have declared as a naked, ordinary method that belongs to nothing. The method, therefore, does not have access to the fields which belong to the form.
One solution is to move the method, which intends to operate on objects owned by the form, into the form itself.
Tfrm_main = class(TForm)
shp_wheelLeftInside: TShape;
shp_wheelRightInside: TShape;
procedure FormCreate(Sender: TObject);
private
procedure addWheelInsides(); {declare it here}
public
{ Public declarations }
end;
Which you then implement as a method of the form class as :
procedure Tfrm_main.addWheelInsides();
begin
shp_wheelRightInside.Height := 42;
end;
The shp_wheelRightInside field is not visible in your procedure.
Declare the procedure addWheelInsides() inside the form as a method instead to resolve the shp_wheelRightInside scope.
type
Tfrm_main = class(TForm)
shp_wheelLeftInside: TShape;
shp_wheelRightInside: TShape;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure addWheelInsides;
public
{ Public declarations }
end;
If you want to extend the procedure across several units, pass TShape as a parameter instead.

Generics and JSON serialisation in Delphi XE5 reflection

I'm trying to serialise/deserialise the TMySerializableClass declared in the below unit:
unit Unit6;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Generics.Collections, System.SyncObjs, DBXJSon,
DBXJSonReflect;
type
TForm6 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
public
{ Public declarations }
end;
TMySerializableClass<T> = class
MyStringField: string;
MyIntegerField: Integer;
MyBooleanField: Boolean;
end;
var
Form6: TForm6;
implementation
{$R *.dfm}
procedure TForm6.Button1Click(Sender: TObject);
var
Mar: TJSONMarshal; //Serializer
UnMar: TJSONUnMarshal; //UnSerializer
SerializedObject: TJSONObject;
aMySerializableClass1: TMySerializableClass<Integer>;
aMySerializableClass2: TMySerializableClass<Integer>;
aString: string;
begin
try
aMySerializableClass1:= TMySerializableClass<Integer>.Create;
aMySerializableClass2:= TMySerializableClass<Integer>.Create;
Mar:= TJSONMarshal.Create(TJSONConverter.Create);
try
SerializedObject := Mar.Marshal(aMySerializableClass1) as TJSONObject;
finally
Mar.Free;
end;
Memo1.Text:= SerializedObject.ToString;
// UnMarshalling Kid
UnMar := TJSONUnMarshal.Create;
try
aMySerializableClass2 := UnMar.UnMarshal(SerializedObject) as TMySerializableClass<Integer>;
finally
UnMar.Free;
end;
finally
aMySerializableClass1.Free;
aMySerializableClass2.Free;
end;
end;
end.
When I serialise it everything works fine, while when deserialise to a new instantiated variable of the same kind I got the following error:
First chance exception at $74E5C41F. Exception class EConversionError with message 'Internal: Cannot instantiate type Unit6.TMySerializableClass<System.Integer>'. Process Project7.exe (2252)
Edit: this has something to do with the TMySerializableClass<T>, which
is a generic. If I declare it as TMySerializableClass the
deserialisation works fine.
Ideas?
Cannot test on XE5 but on Berlin 10.1 it worked for me after I added alias for instance of generic type as
TMySerializableClassInteger = TMySerializableClass<Integer>;
looks like Delphi does not generate RTTI information if you don't do it.
UPDATE. Seems Delphi does not need alias but just have some declaration of specialized class in interface part of the unit. So if you declare variable or form field as TMySerializableClass<Integer> it will also work.

JSON to StringList using Delphi Xe5

I am using Delphi Xe5 and I have a component that essentially uses IDTCPCLient (sockets) to talk with are server and retrieve data in the form of JSON. I have spared you all the connection code , etc. It works. The returned JSon works as well. The trouble I am having is converting my JSON into a StringList, which I then use to write out a list of values to a listbox and store the rest of the JSON data objects in the TSTrings OBjects property.
I have a number of funny things happen.
1.) I can't for the life of me get the List property to work properly. I use this list to store my JSON. A string value and then the entire object for each item in the list. You will notice that in the JSONToStringList method, I clear the stringlist (it is commented out, becuase when it isn't, my program hangs)
2.) I get dupplicate values in my list after calling the method more than once for multiple JSON sets needed
TConnector = class(TComponent)
private
{ Private declarations }
FList: TStrings;
procedure SetList(const Value: TStrings);
protected
{ Protected declarations }
public
{ Public declarations }
Constructor Create( AOwner : TComponent ); override;
Destructor Destroy; Override;
Procedure GenerateJSON;
Procedure JSONToStringList(aJSonKey: String);
published
{ Published declarations }
property List: TStrings Read FList Write SetList;
end;
Constructor TConnector.Create(AOwner: TComponent);
begin
inherited;
FList:= TStringList.Create(True);
end;
destructor TConnector.Destroy;
begin
if FList <> nil then
FreeAndNil(FList);
inherited;
end;
Procedure TConnector.GenerateJSON;
begin
if ResponseStream<>nil then
Begin
FreeAndNil(ResponseJSON_V);
ResponseJSON_V := TJSONObject.ParseJSONValue(StreamToArray(ResponseStream),0) as TJSONValue;
End;
end;
procedure TConnector.JSONToStringList(aJSonKey: String);
Var
zLJsonValue : TJSONValue;
zLJSONArray: TJSONArray;
zLJsonObject : TJSONObject;
zI : Integer;
begin
if ResponseJSON_V is TJSONArray then
begin
zLJSONArray:= ResponseJSON_V as TJSONArray;
zLJsonObject := zLJSONArray.Get(0) as TJSONObject;
end
else
if ResponseJSON_V is TJSONObject then
begin
zLJSONArray:= nil;
zLJsonObject := ResponseJSON_V as TJSONObject;
end
else
Exit;
if zLJSONArray<>nil then
begin
***//FList.Clear;***
for zLJsonValue in zLJSONArray do
begin
zLJsonObject := zLJsonValue as TJSONObject;
for zI := 0 to zLJsonObject.Size-1 do
begin
if zLJsonObject.Get(zI).JsonString.Value = aJSonKey then
begin
FList.AddObject(zLJsonObject.Get(zI).JSONValue.Value, zLJsonObject);
end;
end;
end;
end
else
begin
FList.Clear;
for zI := 0 to zLJsonObject.Size-1 do
begin
if zLJsonObject.Get(zI).JsonString.Value = aJSonKey then
FList.AddObject(zLJsonObject.Get(zI).JSONValue.Value, TJSONPair(zLJsonObject.Get(zI)));
end;
end;
end;
I hope this is all understandable. Please let me know if you need to see more. Please feel free to correct anything else you see bad in my code. I am always learning :) - thank you for your help
If FList.Clear hangs then it's most likely memory corruption issue. First two thing I would suspect is that you have not called a constructor or that part of the memory has been overwritten by something else.
Can the duplicate values in the list be cause by the fact that you commented out FList.Clear. Anyway, I suggest using a debugger to see what goes in to the list or log everything added to/removed from the list. This should give you the idea where unneeded values in the list are coming from.
As a general advice you don't need to check if object is not nil before freeing it. The check is made in Free (or in the Free part of the FreeAndNil) anyway.
It turns out , that the FList property should not have been published, but rather made public instead. Which makes since, cause the list is only filled and emptied at runtime, never at design time.
TLiveConnector = class(TComponent)
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
List: TStrings;
published
end;
Not sure exactly why that is the case, but it seem to work just fine now
Calling List.Clear instead of FList.Clear;
your code cannot work ... U define a param called "aJSonKey" and u call it "ResponseJSON_V " into the procedure.
Moreover u call this "ResponseJSON_V" into GenerateJSON proc when there is no property called that way.

How to embed MySQL (libmysqld.dll) using Delphi ZEOS

I'm trying to use embedded mysql database using libmysqld.dll (mysql 5.1) with zeos (7.0.3) in Delphi XE
i put libmysqld.dll in the same directory,
folder language\errmsg.sys
folder data\belajar\biodata.frm,biodata.MYD,biodata.MYI,db.opt
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ZAbstractConnection, ZConnection;
type
TForm1 = class(TForm)
Button1: TButton;
ZCon: TZConnection;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
ZCon.Protocol := 'mysqld-5';
zcon.Database := 'belajar';
zcon.Connect;
end;
end.
When i run the code, click the button1 and then it just closed, no error message, the application terminated.
any help?
update:
i have solved this problem, i put the wrong name and version of "language" folder, it should be "share" folder and errmsg.sys in the english subfolder
thankyou everyone