Executes a subroutine at a specified address and returns a Long or Large value.
dw = StdCall(addr)([parameters])
lg = LStdCall(addr)([parameters])
dw | : Long |
lg | : Large |
addr | : iexp |
parameters | : aexp |
Both functions are used to call a procedure (not a function) using its address (enclosed in the first set of brackets and which can be derived with ProcAddr) and send the required parameters (enclosed in the second pair of brackets in the order they are expected by the called routine). This is useful in a number of situations, examples being a block of machine/assembly code stored inline or when you wish to call a routine in the main program from a library.
The parameters are 32-bit integers by default but can be coerced to a specific format by preceding the value with one of the following designators:
Cur | Currency | Dbl | Double | Int | Integer |
L | Long | Large | Large integer | Sng | Float, Single |
Var | Variant | W | Word/16-bit Integer |
In addition, you can send strings, types and arrays of all types ByRef (only) by passing the address (* Operator) of the object as one of the parameters. Passing OCX controls is also possible by passing the handle and reconstructing it in the called procedure using Ocx(); similarly, pictures can be passed by hBmp and recreated with CreatePicture.
NOTE: There is currently no known way of passing a Byte variable/value to the stack.
If you wish to get a return value - as in a Function - then this should be added to the eax register for StdCall and eax:edx for LStdCall as in the example below.
Trace StdCall(ProcAddr(test1))( Large:2, 3 )
Trace LStdCall(ProcAddr(test2))( Large:6, 4 )
Debug.Show
Procedure test1(la As Large, i%)
Trace la
Trace i%
i% = la * i%
. mov eax, i%
EndProc
Procedure test2(la As Large, i%)
Local hl%, ll%
Trace la
Trace i%
la = i% * la
hl% = HiLarge(la) : ll% = LoLarge(la)
. mov eax, ll%
. mov edx, hl%
EndProc
A Procedure takes it parameters by value using the StdCall convention. StdCall is the default calling convention for GFA-BASIC 32 and Windows.
If you are calling assembly or C code, [L]StdCall()() expects the subroutine to clear the stack - this is done by ending the code with 'ret xx' where xx is the memory size of all the parameters passed; however, if you are calling a GFABASIC procedure, this is not necessary and will, in fact, cause an error.
The parameters (when 4 bytes in size) are placed onto the stack as follows:
a% = StdCall(addr%)(1, 2, 3)
12[esp] 3
8[esp] 2
4[esp] 1
[esp] return address
If the called code is assembly or C, it should be terminated with 'ret 12'.
The only workaround is to replace StdCall with assembly code, as explained by Sjouke below:
"The heart of StdCall is nothing more than – in assembler –
. mov eax, address
. call eax
"Besides this, StdCall puts the parameters on the stack, saves the state of the CPU, and calls the function at the passed address. Before returning it restores the state of the CPU and StdCall checks the stack pointer, it must be the same as before invoking the function. That is where the error occurs, somehow the stack is corrupted, or GB thinks so."[Reported by Sjouke Hamstra, 22/07/2019]
C:(), LC:(), P:(), LP:(), Call(), CallX(), CCall(), LCCall(), PasCall(), LPasCall()
{Created by Sjouke Hamstra; Last updated: 03/09/2021 by James Gaite; Other Contributors: Jean-Marie Melanson}