Calling a function outside with arguments in different type in TThread.Execute lazarus / 64-FPC development ---------------------------------------------------------------------- sainimu78 · 2016-12-07 11:42 I'm tired of writing lots of lines to do just calling a function when synchronizing. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i trd.arg1 := str;trd.arg2 := num;trd.Synchronize(@Proc);  I tried to simplify, then the calling becomes Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  TMyThread = class(TThread)  public    procedure Execute; override;  end;   { TForm1 }   TForm1 = class(TForm)    StartThread:TButton;    ComboBox1:TComboBox;    procedure AddStr(pArgStr:PString; pArgCnt:PInteger);                function AddStr2(pArgStr:PString; pArgCnt:PInteger):Integer;    procedure DelStr(pArgIdx:PInteger);    procedure StartThreadClick(Sender:TObject);  private    { private declarations }  public    { public declarations }  end; var  Form1: TForm1;  g_cnt:Integer=0;  g_str:string='demostr'; implementation { TForm1 } procedure TMyThread.Execute;var  idx:Integer;begin  g_cnt := MainSyncExecuteInt32Ret(TCallBack(@Form1.AddStr2), [@g_str, @g_cnt]);  idx := g_cnt - 1;  mainSync.Execute(TCallBack(@Form1.DelStr), [@idx]);  mainSync.Execute(TCallBack(@Form1.AddStr), [@g_str, @g_cnt]);end; procedure TForm1.AddStr(pArgStr:PString; pArgCnt:PInteger);begin  ComboBox1.Items.Add(pArgStr^ + ', ' + IntToStr(pArgCnt^));end; function TForm1.AddStr2(pArgStr:PString; pArgCnt:PInteger):Integer;begin  ComboBox1.Items.Add(pArgStr^ + ', ' + IntToStr(pArgCnt^));  result := ComboBox1.Items.Count;end; procedure TForm1.DelStr(pArgIdx:PInteger);begin        ComboBox1.Items.Delete(pArgIdx^);end; procedure TForm1.StartThreadClick(Sender:TObject);begin  with TMyThread.Create(True) do        begin    FreeOnTerminate := True;    Start;  end;end; Supports all args of Pointer only. The TMainSync and TFuncCallStack is here Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  { TMainSync } procedure TMainSync.Execute(argFunc:TCallback; arrArgs:array of const);begin  Execute(TFuncCallStack.Create(argFunc, arrArgs));end; function TMainSync.Execute(argStk:TFuncCallStackBase):Pointer;begin  EnterCriticalsection(lock);  fArgStk := argStk;  TThread.Queue(nil, @Sync);  if(GetCurrentThreadId <> MainThreadId)then  begin    BasicEventWaitForEvent(pEvt, -1);  end  else  begin    argStk.Call;  end;  result := argStk.ret;  argStk.Free;  LeaveCriticalsection(lock);end; procedure TMainSync.Sync;begin  fArgStk.Call;  BasicEventSetEvent(pEvt);end; type   TCallBack = procedure() of object;  TCallback0Args = procedure() of object;  TCallback1Args = procedure(arg1:Pointer) of object;  TCallback2Args = procedure(arg1:Pointer; arg2:Pointer) of object;  TCallback3Args = procedure(arg1:Pointer; arg2:Pointer; arg3:Pointer) of object;  TCallback4Args = procedure(arg1:Pointer; arg2:Pointer; arg3:Pointer; arg4:Pointer) of object;  TCallback5Args = procedure(arg1:Pointer; arg2:Pointer; arg3:Pointer; arg4:Pointer; arg5:Pointer) of object;  TCallback6Args = procedure(arg1:Pointer; arg2:Pointer; arg3:Pointer; arg4:Pointer; arg5:Pointer; arg6:Pointer) of object;  TCallback7Args = procedure(arg1:Pointer; arg2:Pointer; arg3:Pointer; arg4:Pointer; arg5:Pointer; arg6:Pointer; arg7:Pointer) of object;  TCallback8Args = procedure(arg1:Pointer; arg2:Pointer; arg3:Pointer; arg4:Pointer; arg5:Pointer; arg6:Pointer; arg7:Pointer; arg8:Pointer) of object;  TCallback9Args = procedure(arg1:Pointer; arg2:Pointer; arg3:Pointer; arg4:Pointer; arg5:Pointer; arg6:Pointer; arg7:Pointer; arg8:Pointer; arg9:Pointer) of object;  TCallback10Args = procedure(arg1:Pointer; arg2:Pointer; arg3:Pointer; arg4:Pointer; arg5:Pointer; arg6:Pointer; arg7:Pointer; arg8:Pointer; arg9:Pointer; arg10:Pointer) of object;       { TFuncCallStack } procedure TFuncCallStack.Call;begin  if(Pointer(PtrInt(cbFunc)) = nil)then        Exit;  case numArgs of      0:      TCallback0Args(cbFunc)();        1:      TCallback1Args(cbFunc)(ppArgs[0]);        2:      TCallback2Args(cbFunc)(ppArgs[0], ppArgs[1]);        3:      TCallback3Args(cbFunc)(ppArgs[0], ppArgs[1], ppArgs[2]);        4:    TCallback4Args(cbFunc)(ppArgs[0], ppArgs[1], ppArgs[2], ppArgs[3]);        5:      TCallback5Args(cbFunc)(ppArgs[0], ppArgs[1], ppArgs[2], ppArgs[3], ppArgs[4]);        6:      TCallback6Args(cbFunc)(ppArgs[0], ppArgs[1], ppArgs[2], ppArgs[3], ppArgs[4], ppArgs[5]);        7:      TCallback7Args(cbFunc)(ppArgs[0], ppArgs[1], ppArgs[2], ppArgs[3], ppArgs[4], ppArgs[5], ppArgs[6]);        8:      TCallback8Args(cbFunc)(ppArgs[0], ppArgs[1], ppArgs[2], ppArgs[3], ppArgs[4], ppArgs[5], ppArgs[6], ppArgs[7]);        9:      TCallback9Args(cbFunc)(ppArgs[0], ppArgs[1], ppArgs[2], ppArgs[3], ppArgs[4], ppArgs[5], ppArgs[6], ppArgs[7], ppArgs[8]);        10:   TCallback10Args(cbFunc)(ppArgs[0], ppArgs[1], ppArgs[2], ppArgs[3], ppArgs[4], ppArgs[5], ppArgs[6], ppArgs[7], ppArgs[8], ppArgs[9]);  end;end;   My efforts has been made, but not yet simplied enough. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i mainSync.Execute(TCallBack(@Form1.DelStr), [@idx]);  If the type conversion "TCallback()" can be stripped out and the type of the args among the "[]" can be not just Pointer, then this way becomes realy beatifully simplied calling a function one. ---------------------------------------------------------------------- Remy Lebeau · 2016-12-07 19:59 Quote from: sainimu78 on December 07, 2016, 12:42:07 pmI'm tired of writing lots of lines to do just calling a function when synchronizing. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i trd.arg1 := str;trd.arg2 := num;trd.Synchronize(@Proc);  In Delphi, you can use an anonymous procedure with TThread.Synchronize() and TThread.Queue(): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i trd.Synchronize(  procedure  begin    Proc(str, num);  end);  Or: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i TThread.Synchronize(nil,  procedure  begin    Proc(str, num);  end);  But, while FreePascal does have anonymous procedures, TThread does not support them yet in Synchronize() and Queue().  Might be worth a feature request. ---------------------------------------------------------------------- sainimu78 · 2016-12-10 14:18 Last time I saw your showing and I tried in lazarus, this cannot be compiled. ---------------------------------------------------------------------- Remy Lebeau · 2016-12-10 23:20 Quote from: sainimu78 on December 10, 2016, 03:18:57 pmLast time I saw your showing and I tried in lazarus, this cannot be compiled. Like I said, "TThread does not support [anonymous procedures] yet in Synchronize() and Queue()". ---------------------------------------------------------------------- Cyrax · 2016-12-11 05:06 Actually FPC doesn't (yet) support anonymous procedures/methods. ---------------------------------------------------------------------- Thaddy · 2016-12-11 10:17 There is the similar "blocks" in trunk,but only for FPC for MAC OSX 10.7 and higher. http://wiki.freepascal.org/FPC_New_Features_Trunk#Support_for_interfac ing_with_C_blocks_functionality To me that syntax looks a bit cumbersome compared to the Delphi syntax for anonymous methods. I understand some work has been done in a separate branch,but that seems a bit dead atm. ---------------------------------------------------------------------- PascalDragon · 2017-01-07 13:32 @Thaddy: you put up a link to "New Features Trunk" so why do you think the branch is dead? Yes, because it's been successfully merged to trunk! Also the cblocks feature is mainly for Objective C compatibility. Delphi compatible anonymous functions are in the works however and as soon as they are available classes like TThread will be extended accordingly.