Page 2 of 3

Re: Call procedure with several parameters by name

Posted: Thu Dec 13, 2018 2:19 am
by chi
Kwai chang caine wrote:And i don't understand why...i have an error when the array is freeing :shock:
Apart from a little typo (you wrote: MaxParam = CountString(Parametre$, ",") and not Parameter$) and the fact that arrays start with 0 (why allocate an empty element?), your example works perfectly fine with PB x64 but crashes with PB x86 because the ArraySize returns -1 after the first Call(ArrayParams(0))
I'd call this a bug :!:

Code: Select all

Prototype AllMessages(Param1$ = "", Param2$ = "", Param3$ = "")

Runtime Procedure MessageOneParameter(Text.s)
  MessageRequester("Only one Parameter", Text)
EndProcedure

Runtime Procedure MessageTwoParameters(Text1.s, Text2.s)
  MessageRequester("Two parameters", Text1 + Text2)
EndProcedure

Runtime Procedure MessageThreeParameters(Text1.s, Text2.s, Text3.s)
  MessageRequester("Three parameters", Text1 + Text2 + Text3)
EndProcedure

Procedure CallProcedure(NomProcedure.s, Parameter$)
  
  *PtrProc = GetRuntimeInteger(NomProcedure + "()")
  Call.AllMessages = *PtrProc
  MaxParam = CountString(Parameter$, ",") 
  Protected Dim ArrayParams.s(MaxParam)

  For i = 0 To MaxParam
    ArrayParams(i) = StringField(Parameter$, i+1, ",")
  Next
  
  Debug "Pre Call Size = " + ArraySize(ArrayParams()) 
  
  Select MaxParam
    Case 0
      Call(ArrayParams(0))
    Case 1
      Call(ArrayParams(0), ArrayParams(1))
    Case 2
      Call(ArrayParams(0), ArrayParams(1), ArrayParams(2))
  EndSelect
  
  Debug "Post Call Size = " + ArraySize(ArrayParams()) 
  Debug "------------------"
  
  FreeArray(ArrayParams())
  
EndProcedure

CallProcedure("MessageOneParameter", "Hello it's KCC")
CallProcedure("MessageTwoParameters", "Hello it's KCC a second time, but it's more long")
CallProcedure("MessageThreeParameters", "Hello it's KCC another time, and this time, it's one time too much")
[/size]

Re: Call procedure with several parameters by name

Posted: Fri Dec 14, 2018 7:14 pm
by Kwai chang caine
Hello THE.WEAVSTER :D
Thanks for your code, with it it's really more simple to manage parameters 8)
Chi wrote:your example works perfectly fine with PB x64 but crashes with PB x86
Hello CHI :D
You have totaly right, i have download and compile in x64 for see, and me too that works in X64 :shock:
Pre Call Size = -1
Post Call Size = -1
------------------
Pre Call Size = 1
Post Call Size = -1
------------------
Pre Call Size = 2
Post Call Size = -1
------------------
Pre Call Size = 3
Post Call Size = -1
------------------
Thanks a lot Master CHI for have found this problem 8), because yesterday i have continue to reflect on my exemple, and not understand this crash :|

Code: Select all

Prototype AllMessages(Param1$ = "", Param2$ = "", Param3$ = "")

Runtime Procedure MessageWithoutParameter()
 MessageRequester("Without Parameter", "No parameter")
EndProcedure

Runtime Procedure MessageOneParameter(Text.s)
 MessageRequester("Only one Parameter", Text)
EndProcedure

Runtime Procedure MessageTwoParameters(Text1.s, Text2.s)
 MessageRequester("Two parameters", Text1 + Text2)
EndProcedure

Runtime Procedure MessageThreeParameters(Text1.s, Text2.s, Text3.s)
 MessageRequester("Three parameters", Text1 + Text2 + Text3)
EndProcedure

Procedure CallProcedure(NomProcedure.s, Parameter$ = "")
 
 *PtrProc = GetRuntimeInteger(NomProcedure + "()")
 Call.AllMessages = *PtrProc
 MaxParam = 0
 
 If Parameter$ <> ""
    
  MaxParam = CountString(Parameter$, ",") + 1
  Protected Dim ArrayParams.s(MaxParam)
 
  For i = 1 To MaxParam
   ArrayParams(i) = StringField(Parameter$, i, ",")
  Next
  
 EndIf
    
 Debug "Pre Call Size = " + ArraySize(ArrayParams())
 
 Select MaxParam
  Case 0
   Call()
  Case 1
   Call(ArrayParams(1))
   FreeArray(ArrayParams())
  Case 2
   Call(ArrayParams(1), ArrayParams(2))
   FreeArray(ArrayParams())
  Case 3 
   Call(ArrayParams(1), ArrayParams(2), ArrayParams(3))
   FreeArray(ArrayParams())
 EndSelect
 
 Debug "Post Call Size = " + ArraySize(ArrayParams())
 Debug "------------------"
  
EndProcedure

CallProcedure("MessageWithoutParameter")
CallProcedure("MessageOneParameter", "Hello it's KCC")
CallProcedure("MessageTwoParameters", "Hello it's KCC a second time, but it's more long")
CallProcedure("MessageThreeParameters", "Hello it's KCC another time, and this time, it's one time too much")
The problem it's this time...is i'm not enough intelligent for explain that, to FRED :oops:

Surely he say to KCC, it's normal because he not use PB correctly, and when KCC not know the "PROTOTHINGS" it's better for him go to pick strawberries :mrgreen:
Never mind, i take the risk, and try to create a "Bug THREAD" about this subject for know the final word of this history, and know if it's or not my fault :wink:
viewtopic.php?p=530293#p530293

@ALL
Again thanks at all, for all your kind messages and precious helps

Kcc love you all !!!
Image

Re: Call procedure with several parameters by name

Posted: Sat Dec 15, 2018 1:50 am
by breeze4me
It crashes in x86 because of the difference between x86 calling convention and x64 calling convention, so you should use PrototypeC and ProcedureC.

Code: Select all

PrototypeC AllMessages(Param1$ = "", Param2$ = "", Param3$ = "")

Runtime ProcedureC MessageOneParameter(Text.s)
  MessageRequester("Only one Parameter", Text)
EndProcedure

Runtime ProcedureC MessageTwoParameters(Text1.s, Text2.s)
  MessageRequester("Two parameters", Text1 + Text2)
EndProcedure

Runtime ProcedureC MessageThreeParameters(Text1.s, Text2.s, Text3.s)
  MessageRequester("Three parameters", Text1 + Text2 + Text3)
EndProcedure

Procedure CallProcedure(NomProcedure.s, Parameter$)
  
  *PtrProc = GetRuntimeInteger(NomProcedure + "()")
  Call.AllMessages = *PtrProc
  MaxParam = CountString(Parameter$, ",") 
  Protected Dim ArrayParams.s(MaxParam)

  For i = 0 To MaxParam
    ArrayParams(i) = StringField(Parameter$, i+1, ",")
  Next
  
  Debug "Pre Call Size = " + ArraySize(ArrayParams()) 
  
  Select MaxParam
    Case 0
      Call(ArrayParams(0))
    Case 1
      Call(ArrayParams(0), ArrayParams(1))
    Case 2
      Call(ArrayParams(0), ArrayParams(1), ArrayParams(2))
  EndSelect
  
  FreeArray(ArrayParams())
  
  Debug "Post Call Size = " + ArraySize(ArrayParams()) 
  Debug "------------------"
  
EndProcedure

CallProcedure("MessageOneParameter", "Hello it's KCC")
CallProcedure("MessageTwoParameters", "Hello it's KCC a second time, but it's more long")
CallProcedure("MessageThreeParameters", "Hello it's KCC another time, and this time, it's one time too much")

Re: Call procedure with several parameters by name

Posted: Sat Dec 15, 2018 9:51 am
by Kwai chang caine
Yeeeesss !!!!
You have totaly right, your code fix the bug !!! :shock:
Thanks to have found it 8)

Then, at your advice ..... is it a bad use of KCC, or an not normal behavior ?

Re: Call procedure with several parameters by name

Posted: Sat Dec 15, 2018 10:04 am
by chi
breeze4me wrote:It crashes in x86 because of the difference between x86 calling convention and x64 calling convention, so you should use PrototypeC and ProcedureC.
Unfortunately [ Debug "Post Call Size = " + ArraySize(ArrayParams()) ] still returns -1 (also on x64 now)

Re: Call procedure with several parameters by name

Posted: Sat Dec 15, 2018 1:13 pm
by breeze4me
Kwai chang caine wrote: Then, at your advice ..... is it a bad use of KCC, or an not normal behavior ?
a call stack corruption... it's not a good use. :wink:

chi wrote: Unfortunately [ Debug "Post Call Size = " + ArraySize(ArrayParams()) ] still returns -1 (also on x64 now)
ArrayParams() was freed, then the size is -1. It's normal.

Code: Select all

ArraySize()
......
Returns the size of the array dimension. If the array isn't yet declared (or its allocation has failed), it will return -1.

FreeArray()
......
Free the specified 'Array()' and release all its associated memory. To access it again Dim has to be called. 

Code: Select all

......
  FreeArray(ArrayParams())
  
  Debug "Post Call Size = " + ArraySize(ArrayParams()) 
  Debug "------------------"
......

Re: Call procedure with several parameters by name

Posted: Sat Dec 15, 2018 1:24 pm
by chi
breeze4me wrote:ArrayParams() was freed, then the size is -1. It's normal.
Good point... You have changed the order (FreeArray() before ArraySize). I've missed that :oops:

Re: Call procedure with several parameters by name

Posted: Sat Dec 15, 2018 1:55 pm
by Kwai chang caine
breeze4me wrote:a call stack corruption... it's not a good use.
Aaaah ok ! :oops: Thanks MASTER for your explanation 8)
So, i want good understand, i must use your code with PrototypeC /ProcedureC or i don't use the prototype for this code :?:

@CHI
Again thanks CHI for your great help and your support in the other THREAD :wink: , it warmed my heart 8)
Before, you are for me one of my heroes, but this time i'm sure you are an hero, MASTER CHI rescue little KCC :lol:

Image

Re: Call procedure with several parameters by name

Posted: Sat Dec 15, 2018 2:22 pm
by breeze4me
Kwai chang caine wrote:
breeze4me wrote:a call stack corruption... it's not a good use.
Aaaah ok ! :oops: Thanks MASTER for your explanation 8)
So, i want good understand, i must use your code with PrototypeC /ProcedureC or i don't use the prototype for this code :?:
Using PrototypeC /ProcedureC is a good way. But using Prototype/Procedure is no problem with some additional parts.
See the following code.

Code: Select all

Prototype AllMessages(Param1$ = "", Param2$ = "", Param3$ = "")

Runtime Procedure MessageOneParameter(Text.s, Param2$ = "", Param3$ = "")
  MessageRequester("Only one Parameter", Text)
EndProcedure

Runtime Procedure MessageTwoParameters(Text1.s, Text2.s, Param3$ = "")
  MessageRequester("Two parameters", Text1 + Text2)
EndProcedure

Runtime Procedure MessageThreeParameters(Text1.s, Text2.s, Text3.s)
  MessageRequester("Three parameters", Text1 + Text2 + Text3)
EndProcedure

Procedure CallProcedure(NomProcedure.s, Parameter$)
  
  *PtrProc = GetRuntimeInteger(NomProcedure + "()")
  Call.AllMessages = *PtrProc
  MaxParam = CountString(Parameter$, ",") 
  Protected Dim ArrayParams.s(MaxParam)

  For i = 0 To MaxParam
    ArrayParams(i) = StringField(Parameter$, i+1, ",")
  Next
  
  Debug "Pre Call Size = " + ArraySize(ArrayParams()) 
  
  Select MaxParam
    Case 0
      Call(ArrayParams(0))
    Case 1
      Call(ArrayParams(0), ArrayParams(1))
    Case 2
      Call(ArrayParams(0), ArrayParams(1), ArrayParams(2))
  EndSelect
  
  FreeArray(ArrayParams())
  
  Debug "Post Call Size = " + ArraySize(ArrayParams()) 
  Debug "------------------"
  
EndProcedure

CallProcedure("MessageOneParameter", "Hello it's KCC")
CallProcedure("MessageTwoParameters", "Hello it's KCC a second time, but it's more long")
CallProcedure("MessageThreeParameters", "Hello it's KCC another time, and this time, it's one time too much")

Re: Call procedure with several parameters by name

Posted: Sat Dec 15, 2018 2:35 pm
by Kwai chang caine
Aaaah!!! i have understand now what you try to explain kindly to me 8)

In fact my error is the prototype must have exactely the same number of parameters as the procedure called like this

Code: Select all

Prototype AllMessages(Param1$ = "", Param2$ = "", Param3$ = "")

Runtime Procedure MessageOneParameter(Text.s, Param2$ = "", Param3$ = "")
  MessageRequester("Only one Parameter", Text)
EndProcedure
Then i can't use prototype, in this form, if i have this procedure like this

Code: Select all

Prototype AllMessages(Param1$ = "", Param2$ = "", Param3$ = "")

Runtime Procedure MessageOneParameter(Text.s)
  MessageRequester("Only one Parameter", Text)
EndProcedure
In fact,.....it's exactely what "Little John" explain to me, but with a little bit different method :mrgreen:
Image

and i must recognize, that does not have the same effect on me :oops:

Thanks a lot Breeze4Me for your precious help
Have a good day 8)

Re: [Resolved] Call procedure with several parameters by nam

Posted: Sun Dec 16, 2018 3:01 am
by Kwai chang caine
Thanks to several advices (Include Little John) i modify my code and apparently it works on X86 8)

Code: Select all

Prototype P0()
Prototype P1(Param1$ = "")
Prototype P2(Param1$ = "", Param2$ = "")
Prototype P3(Param1$ = "", Param2$ = "", Param3$ = "")
Prototype P4(Param1$ = "", Param2$ = "", Param3$ = "", Param4$ = "")
Prototype P5(Param1$ = "", Param2$ = "", Param3$ = "", Param4$ = "", Param5$ = "")

Runtime Procedure MessageWithoutParameter()
 MessageRequester("Without Parameter", "No parameter")
EndProcedure

Runtime Procedure MessageOneParameter(Text.s)
 MessageRequester("Only one Parameter", Text)
EndProcedure

Runtime Procedure MessageTwoParameters(Text1.s, Text2.s)
 MessageRequester("Two parameters", Text1 + Text2)
EndProcedure

Runtime Procedure MessageThreeParameters(Text1.s, Text2.s, Text3.s)
 MessageRequester("Three parameters", Text1 + Text2 + Text3)
EndProcedure

Procedure CallProcedure(NomProcedure.s, Parameter$ = "")
 
 *PtrProc = GetRuntimeInteger(NomProcedure + "()")
 MaxParam = CountString(Parameter$, ",") + Bool(Parameter$ <> "")
 Protected Dim ArrayParams.s(MaxParam)
 
 If MaxParam
 
  For i = 1 To MaxParam
   ArrayParams(i) = StringField(Parameter$, i, ",")
  Next
  
 EndIf
 
 Debug "Pre Call Size = " + ArraySize(ArrayParams())
 
 Select MaxParam
  Case 0
   Call.P0 = *PtrProc
   Call()
  Case 1
   Call.P1 = *PtrProc
   Call(ArrayParams(1))
  Case 2
   Call.P2 = *PtrProc
   Call(ArrayParams(1), ArrayParams(2))
  Case 3
   Call.P3 = *PtrProc
   Call(ArrayParams(1), ArrayParams(2), ArrayParams(3))
  Case 4
   Call.P4 = *PtrProc
   Call(ArrayParams(1), ArrayParams(2), ArrayParams(3),ArrayParams(4))
  Case 5
   Call.P5 = *PtrProc
   Call(ArrayParams(1), ArrayParams(2), ArrayParams(3), ArrayParams(4), ArrayParams(5))
 EndSelect
 
 Debug "Post Call Size = " + ArraySize(ArrayParams())
 Debug "------------------"
 
 FreeArray(ArrayParams())
 
EndProcedure

CallProcedure("MessageWithoutParameter")
CallProcedure("MessageOneParameter", "Hello it's KCC")
CallProcedure("MessageTwoParameters", "Hello it's KCC a second time, but it's more long")
CallProcedure("MessageThreeParameters", "Hello it's KCC another time, and this time, it's one time too much")
Thanks again at all 8)

PS:Fixed thanks to MESTNYI 8)

Re: [Resolved] Call procedure with several parameters by nam

Posted: Sun Dec 16, 2018 8:08 am
by mestnyi
Here are my two pennies.
So I think it will be faster more beautiful and clearer.

Code: Select all

MaxParam = CountString(Parameter$, ",")
 Protected Dim ArrayParams.s(MaxParam)
 MaxParam = 0
 
 If Parameter$ <> ""
   
  MaxParam = CountString(Parameter$, ",") + 1
  Protected Dim ArrayParams.s(MaxParam)
 
  For i = 1 To MaxParam
   ArrayParams(i) = StringField(Parameter$, i, ",")
  Next
 
 EndIf

Code: Select all

MaxParam = CountString(Parameter$, ",") + Bool(Parameter$ <> "")
  Protected Dim ArrayParams.s(MaxParam)
  
  If MaxParam
    For i = 1 To MaxParam
      ArrayParams(i) = StringField(Parameter$, i, ",")
    Next 
  EndIf
  

Re: [Resolved] Call procedure with several parameters by nam

Posted: Sun Dec 16, 2018 6:05 pm
by Kwai chang caine
Hello MESTNYI :D

Really interesting this part of your code :shock: we recognize the MASTER touch 8)

Code: Select all

+ Bool(Parameter$ <> "")
You have right, two time the same lines

Code: Select all

 MaxParam = CountString(Parameter$, ",") + 1
  Protected Dim ArrayParams.s(MaxParam)
and between erase "MaxParam' :shock:

By force, to all test, in every way....

Image

sometime it's better to go to bed :oops: or maybe again better...never leave it :mrgreen:
Thanks MASTER for your help 8)

To reach my primary goal, i search now if it's possible to write under this form (more professional 8) )

Code: Select all

CallProcedure("MessageTwoParameters", "Hello it's KCC a second time" ,  "but it's more long")
CallProcedure("MessageThreeParameters", "Hello it's KCC another time" , "and this time" , "it's one time too much")
instead of this, less nice :|

Code: Select all

CallProcedure("MessageTwoParameters", "Hello it's KCC a second time, but it's more long")
CallProcedure("MessageThreeParameters", "Hello it's KCC another time, and this time, it's one time too much")
But i believe, in PB it's impossible to count or know the numbers of parameters of a procedure :cry:

It's a pity "GetRuntimeString()" is not used for procedure :|
viewtopic.php?p=517231#p517231
That would be great if this function return the full procedure name "MessageThreeParameters(Text1.s, Text2.s, Text3.s)" if it's possible :idea:

Code: Select all

Runtime Procedure MessageThreeParameters(Text1.s, Text2.s, Text3.s)
 MessageRequester("Three parameters", Text1 + Text2 + Text3)
EndProcedure

Debug "Pointer of procedure = " + Trim(Str(GetRuntimeInteger("MessageThreeParameters" + "()")))
Debug "Full call of procedure = " + GetRuntimeString("MessageThreeParameters" + "()")
Compiler wrote:Pointer of procedure = 4198787
Full call of procedure = MessageThreeParameters(Text1.s, Text2.s, Text3.s)
Like this, i could count the numbers of parameters 8)

Again thanks for your interest
Have a good day

Re: [Resolved] Call procedure with several parameters by nam

Posted: Thu Dec 20, 2018 1:06 pm
by Mijikai
This is a nice idea :)

I tried to make something that supports all parameter types.
However it fails and i dont know exactly why. :cry:
I thought it should not matter if the parameter is a int, float or double (in x64 asm all will be pushed as 8 bytes)...

Mby someone can tell my why i cant do this:

Code: Select all

;PB 5.62 x64

EnableExplicit

Global str.s
Global flt.f
Global par.i

Procedure.i ProcTest(TestString.s,TestParameter.f)
  MessageRequester("Test! ",TestString + " "  + StrF(TestParameter,3))
EndProcedure

str = "Hello World!"
flt = 123.456
par = PeekL(@flt)

Debug flt
PokeL(@flt,par)
Debug flt

ProcTest(str,flt)

CallFunctionFast(@ProcTest(),@str,flt);fails !?
CallFunctionFast(@ProcTest(),@str,par);fails !?

End
-> CallFunctionFast() always fails!!!

Re: [Resolved] Call procedure with several parameters by nam

Posted: Thu Dec 20, 2018 2:25 pm
by Kwai chang caine
Mijikai wrote:This is a nice idea
Thanks, it's an honor coming from you 8)
Obviously, i"m not enough strong for help you :oops:
I hope another MASTER can help
Mijikai wrote:-> CallFunctionFast() always fails!!!
Apparently not for me with W7 X86 / v5.62 x86

Here, only the first call

Code: Select all

CallFunctionFast(@ProcTest(),@str,flt)
return "0" in the second parameter "TestParameter" :wink:
The second

Code: Select all

CallFunctionFast(@ProcTest(),@str,par)
return "123.456"