Page 1 of 3

Re: How to create Arguments like CallFunctionFast

Posted: Mon Dec 05, 2011 10:19 am
by wilbert
As far as I know you can't.
PureBasic has no support for a rest operator (...)

Re: How to create Arguments like CallFunctionFast

Posted: Mon Dec 05, 2011 10:20 am
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

Re: How to create Arguments like CallFunctionFast

Posted: Mon Dec 05, 2011 11:29 am
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.

Re: How to create Arguments like CallFunctionFast

Posted: Mon Dec 05, 2011 11:38 am
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

Re: How to create Arguments like CallFunctionFast

Posted: Mon Dec 05, 2011 12:32 pm
by Env
Look Here for a possible solution.

Re: How to create Arguments like CallFunctionFast

Posted: Mon Dec 05, 2011 8:27 pm
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.

Re: How to create Arguments like CallFunctionFast

Posted: Mon Dec 05, 2011 8:35 pm
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...

Re: How to create Arguments like CallFunctionFast

Posted: Tue Dec 06, 2011 12:15 pm
by einander
May be the use of prototypes here can help:

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

Cheers!

Re: How to create Arguments like CallFunctionFast

Posted: Wed Dec 07, 2011 3:01 pm
by wilbert
I don't understand why you are not simply using the Import statement. :?

Re: How to create Arguments like CallFunctionFast

Posted: Thu Dec 08, 2011 1:40 pm
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.

Re: How to create Arguments like CallFunctionFast

Posted: Thu Dec 08, 2011 5:35 pm
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?

Re: How to create Arguments like CallFunctionFast

Posted: Thu Dec 08, 2011 5:51 pm
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.

Re: How to create Arguments like CallFunctionFast

Posted: Thu Dec 08, 2011 6:10 pm
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.

Re: How to create Arguments like CallFunctionFast

Posted: Thu Dec 08, 2011 9:14 pm
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.

Re: How to create Arguments like CallFunctionFast

Posted: Thu Dec 08, 2011 11:27 pm
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())