How to create Arguments like CallFunctionFast

Just starting out? Need help? Post your questions and find answers here.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: How to create Arguments like CallFunctionFast

Post by wilbert »

As far as I know you can't.
PureBasic has no support for a rest operator (...)
gnasen
Enthusiast
Enthusiast
Posts: 282
Joined: Wed Sep 24, 2008 12:21 am

Re: How to create Arguments like CallFunctionFast

Post by gnasen »

there is no native way in PB like in Java or C.
However you can make a little workaround like an array, list or structured memory. At the moment I have not PB to test, but something like this should work (array)

Code: Select all

procedure bla(array intArray.i(1))
  for a=0 to arraysize(intArray())
    debug intArray(a)
  next
endprocedure
pb 5.11
User avatar
Bisonte
Addict
Addict
Posts: 1305
Joined: Tue Oct 09, 2007 2:15 am

Re: How to create Arguments like CallFunctionFast

Post by Bisonte »

or you set it to max parameters with

Code: Select all

Procedure CF(a=0,b=0,c=0,d=0.........)
or use a structured pointer

Code: Select all

Structure myparamlist
param1.i
param2.i
...
EndStructure
Procedure CF(*pointer.myparamlist)
Debug *pointer\param1
EndProcedure
But in all facts, you have to know, how many params the procedure max have.
PureBasic 6.21 (Windows x64) | Windows 11 Pro | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
English is not my native language... (I often use DeepL.)
User avatar
Guimauve
Enthusiast
Enthusiast
Posts: 742
Joined: Wed Oct 22, 2003 2:51 am
Location: Canada

Re: How to create Arguments like CallFunctionFast

Post by Guimauve »

I'm not sure if this code will help you but

Code: Select all

Procedure MyProcAlpha()
  
  Debug #PI
  
EndProcedure  

Procedure MyProcBeta(a.f)
  
  Debug a * #PI
  
EndProcedure  

Procedure MyProcGamma(a.f, b.f)
  
  Debug a + b
  
EndProcedure  

Procedure MyProcZeta(a.f, b.f, c.f)
  
  Debug a + b + c
  
EndProcedure  

Procedure Call(ParamCount, func, Param00.f = 0.0, Param01.f = 0.0, Param02.f = 0.0)
  
  Select ParamCount
      
    Case 0
      CallFunctionFast(func)
      
    Case 1
      CallFunctionFast(func, Param00)
      
    Case 2
      CallFunctionFast(func, Param00, Param01)
      
    Case 3
      CallFunctionFast(func, Param00, Param01, Param02)
      
  EndSelect 
  
EndProcedure  

VarB.f = 1.5
VarC.f = 2.5
VarD.f = 3.5

Call(0, @MyProcAlpha())

Call(1, @MyProcBeta(), VarB)

Call(2, @MyProcGamma(), VarB, VarC)

Call(3, @MyProcZeta(), VarB, VarC, VarD)
Best regards.
Guimauve
Env
Enthusiast
Enthusiast
Posts: 151
Joined: Tue Apr 27, 2010 3:20 pm
Location: Wales, United Kingdom

Re: How to create Arguments like CallFunctionFast

Post by Env »

Look Here for a possible solution.
Thanks!
Env
Enthusiast
Enthusiast
Posts: 151
Joined: Tue Apr 27, 2010 3:20 pm
Location: Wales, United Kingdom

Re: How to create Arguments like CallFunctionFast

Post by Env »

I personally haven't a clue what you're asking.. are you asking what the API alternative to CallFunctionFast is?

So for instance: CallFunctionFast is CallFunction_(...)?

In the land of C++, you declare a function as you would a Prototype in PureBasic, and you then assign a pointer to that declaration, creating a definition.. this is the definition that is called.

I would imagine in PureBasic, the CallFunctionFast(...) is not just a wrapper to an API call, but a function that takes the arguments into account, so that it can put the required data into the stack for the called function to query.
Thanks!
Zach
Addict
Addict
Posts: 1675
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: How to create Arguments like CallFunctionFast

Post by Zach »

I could be wrong but I think this is what he is asking...

He wants to write a function, that can take an indeterminate amount of Parameters..

i.e it could be Foo(bar, tastes, good) or Foo(bar, junk) etc..

And I think he was using CallFunctionFast to try and illustrate what he was asking for.

i.e You call a function from a DLL/Library using CallFunctionFast, but how does it handle the parameters?? But I think he misunderstands if this is what he is asking, because the function being called is responsible for its parameters and what it expects, not CallFunctionFast itself... Or I could be a little off base too, as I have never used CFF before and have little to no experience with Imports, Prototypes, loading external libraries, etc...
User avatar
einander
Enthusiast
Enthusiast
Posts: 744
Joined: Thu Jun 26, 2003 2:09 am
Location: Spain (Galicia)

Re: How to create Arguments like CallFunctionFast

Post by einander »

May be the use of prototypes here can help:

http://www.purebasic.fr/english/viewtop ... =Prototype

Cheers!
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: How to create Arguments like CallFunctionFast

Post by wilbert »

I don't understand why you are not simply using the Import statement. :?
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Re: How to create Arguments like CallFunctionFast

Post by Psychophanta »

Louise wrote::D :D :D :D
I could write this code. Please help me to optimize my code.

Code: Select all

ProcedureDll OpenLib(Dll.s)
 If Dll 
   ProcedureReturn LoadLibrary_(@Dll)
 EndIf 
EndProcedure 
 
ProcedureDll OpenFunc(ID,Func.s)
  If ID
    ProcedureReturn GetProcAddress_(ID,@Func)
  EndIf
EndProcedure

ProcedureDll FreeLib(ID)
  FreeLibrary_(ID)
EndProcedure 


lib = OpenLib("User32.dll")

   func = OpenFunc(lib,"SetCursorPos")
   
   PUSH 100
   PUSH 100
   CALL func
  
FreeLib(lib)
You can know how the function modifies the stack pointer, but i don't know how to know what is the type (size) of each function parameter, i mean if a function modifies the esp value in 8 bytes, then you can know the function uses 2 long values as parameters, or also it could be 8 byte values, or 2 word values and 1 long value, etc.
So , well, as i stated, you alreade can retrieve the amount the stack pointer ('esp' in x86) by calling one time to the function. After this retrieving you can call again with the parameters, but now you know the amount of bytes these parameters must have.
Following your example here it is the way to know the amout of bytes the parameters should fit:

Code: Select all

ProcedureDLL OpenLib(Dll.s)
If Dll 
   ProcedureReturn LoadLibrary_(@Dll)
EndIf 
EndProcedure 

ProcedureDLL OpenFunc(ID,Func.s)
  If ID
    ProcedureReturn GetProcAddress_(ID,@Func)
  EndIf
EndProcedure

ProcedureDLL FreeLib(ID)
  FreeLibrary_(ID)
EndProcedure 

lib = OpenLib("User32.dll")

   func = OpenFunc(lib,"SetCursorPos")
    espdiff.l
   !mov dword[v_espdiff],esp
   
   !;PUSH 100 100
   !CALL dword[v_func]
   
   !sub dword[v_espdiff],esp
   !add esp,dword[v_espdiff]; <- leaves the esp just like it was before the calling
   FreeLib(lib)
   Debug "parameters should fit "+Str(-espdiff)+" bytes"
   
There is 1 big problem with this approach:
- the function will must be runned one time with random parameters.
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Re: How to create Arguments like CallFunctionFast

Post by Psychophanta »

Louise wrote:Ie there's no way that this problem be solved?
I think, however, if you don't know about the parameter requirements of the function you wanna call, then you don't know what is the function you are calling to, and so then you don't know what are you doing. Do you?
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
Zach
Addict
Addict
Posts: 1675
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: How to create Arguments like CallFunctionFast

Post by Zach »

Think of it like this... Before the Age of the Internet, etc..

You have a new job delivering pizza. You have to go to an address in a part of town you've never been. You don't know if you have to turn left on this street, right on the next street, or maybe its another left? You won't know until you see the street sign.
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Re: How to create Arguments like CallFunctionFast

Post by Psychophanta »

Louise wrote:I wrote this code, please look and say your opinions. :D
asm PUSH inside a PB loop is dangerous, because nobody knows what the hell does a pb loop with the stak pointer.
But a fornext loop probably do nothing with the 'esp', so if oyu take care with other commands inside the loop, that way could be done in general.
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Re: How to create Arguments like CallFunctionFast

Post by Psychophanta »

I hope this can be useful

Code: Select all

If OpenLibrary(0,"user32.dll")
  hFunc = GetFunction(0,"MessageBoxA")
  If hFunc
    Dim arg.l(3)
    size.l= ArraySize(arg())
    arg(0) = #Null
    arg(1) = @"title"
    arg(2) = @"caption"
    arg(3) = 0
    !mov ecx,dword[v_size]
    !@@:mov eax,dword[a_arg]
    !push dword[eax+ecx*4]
    !dec ecx
    !jnl @r
    !call dword[v_hFunc]
  EndIf
  CloseLibrary(0)
EndIf
You can also deal it with linked list instead of Array.
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Re: How to create Arguments like CallFunctionFast

Post by Psychophanta »

Functions which return a not float dot value the returned values usually is stored in the 'eax' register:

Code: Select all

Procedure.i CallFast(lib$,Function$,Array Args.l(1))
  If OpenLibrary(0,lib$)
    Protected size.l=ArraySize(Args()),res.i
    Protected hFunc.l=GetFunction(0,Function$)
    If hFunc
      !mov eax,dword[p.v_hFunc]
      !mov ecx,dword[p.v_size]
      !mov edi,dword[p.a_Args]
      !mov edi,dword[edi]
      !@@:push dword[edi+ecx*4]
      !dec ecx
      !jnl @r
      !call eax
      !mov dword[p.v_res],eax; <- in functions commonly there is in 'eax' register where the returned not float value is stored
    EndIf
    CloseLibrary(0)
  EndIf
  ProcedureReturn res
EndProcedure

Dim arg.l(3)
arg(0) = #Null
arg(1) = @"title"
arg(2) = @"caption"
arg(3) = 0
Debug CallFast("user32.dll","MessageBoxA",arg())
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
Post Reply