Calls a native Windows function with the given arguments and outputs the function's return value. The function must be exported by a DLL which was loaded with DLLLOAD.
function_parameter_list is of the form
[typef function type1 arg1 type2 arg2 type3 arg3 ...].
typef as describing the function's return value.
The return value is parsed into a list, as with PARSE.
Any buffers that were created for "out" parameters are appened to the list and it is the output of DLLCALL.
The meaning of each supported
typef is given in the table below:
|typef||Native Type||DLLCALL Output|
|WORD, SHORT, or USHORT||Outputs the lower 16 bits of the function's return value as a one member list.|
|DWORD, LONG, or ULONG||Outputs the function's return value, interpreted as a 32-bit integer, as a one member list.|
|DOUBLE||Outputs the function's return value as a one member list.|
|LPSTR||Copies the returned pointer as a NUL-terminated string of characters and calls GlobalFreePtr() on the returned pointer. The string is then parsed as with PARSE and the resulting list is output.|
function must be a word that exactly matches a symbol which is exported from the DLL.
For Win32 functions that take a parameter of type TCHAR, the exported symbol probably ends in either W or A, even if you wouldn't call it like that from C.
arg1 as a
arg2 as a
type2, and so on.
Keep in mind that the win32 "stdcall" convention pass arguments from right to left, so arg1 is really the last parameter.
The actions taken for each argument are given in the following table:
|type#||Native Type||DLLCALL action|
|void||Ignores the argument|
|WORD, SHORT, or USHORT||Pushes the lowest 16 bits of the argument onto the stack as a 32-bit value.|
|DWORD, LONG, or ULONG||Pushes the integral value of the argument onto the stack as a 32-bit value.|
|DOUBLE||Intereprets the argument as a |
|LPCSTR||Copies the argument into a buffer, adds a NUL terminator, and pushes its pointer onto the stack.|
|PBYTE, PULONG, or LPSTR||Allocates a buffer that has as many bytes as the given argument, when interpreted as an integer. Fills the buffer with zero bytes. Marks it as a "vertical barred" word so that it can hold non-printable bytes. Pushes a pointer to this buffer onto the stack. After the function returns, appends the buffer to the output list. If the function returns void, then a list is created so that the buffer can be output to the caller.|
If the optional
dllname input is given, then DLLCALL only looks for the function within that DLL.
The "B" argument types are returned as buffers of the exact length they were given. Any byte that is not overwritten by the function call remains NUL (zero byte). So if the function fills in a string of characters and only uses part of the buffer, the buffer will have a lot of zero bytes at the end. Such a word does not behave like a regular word. However, you can convert it to a regular word by removing the zero bytes with something like:
MAKE "buffer FILTER [NOTEQUALP CHAR 0 ? ] :buffer
DLLCALL is meant for experienced programmers who are familiar with the native Windows calling conventions. If you do not properly match the argument list the results will be unpredictable and likely crash FMSLogo. DLLCALL can handle a wide variety of function calls but certainly not all.
DLLCALL allows to extend the reach of FMSLogo when its existing commands are insufficient. You can write your own DLL with a compatible call interface to call more complex interfaces.
; Equivalent to the C call ; MessageBox(NULL, "Do you like FMSLogo?", "Question", MB_YESNO); DLLLOAD "user32.dll IGNORE DLLCALL [L MessageBoxA L 4 S [Question] S [Do you like FMSLogo?] L 0]
See a message box pop up.