DLLCALLfunction_parameter_list
(DLLCALLfunction_parameter_list
dllname
)
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.
The function_parameter_list
is of the form [typef function type1 arg1 type2 arg2 type3 arg3 ...]
.
DLLCALL interprets 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 |
---|---|---|
V | void | Nothing |
W | WORD, SHORT, or USHORT | Outputs the lower 16 bits of the function's return value as a one member list. |
L | DWORD, LONG, or ULONG | Outputs the function's return value, interpreted as a 32-bit integer, as a one member list. |
F | DOUBLE | Outputs the function's return value as a one member list. |
S | LPSTR | Copies the data from the returned pointer into a word, interpreting it as a NUL-terminated string of ANSI characters in the system default Windows code page, and calls GlobalFreePtr() on the returned pointer. The word 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.
DLLCALL passes arg1
as a type1
, 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 |
---|---|---|
V | void | Ignores the argument |
W | WORD, SHORT, or USHORT | Pushes the lowest 16 bits of the argument onto the stack as a 32-bit value. |
L | DWORD, LONG, or ULONG | Pushes the integral value of the argument onto the stack as a 32-bit value. |
F | DOUBLE | Interprets the argument as a double and pushes the value as a 64-bit floating point onto the stack. |
S | LPCSTR | Converts the argument to a NUL-terminated string of ANSI characters according to the system default Windows code page and pushes its pointer onto the stack. |
U | LPCWSTR | Converts the argument to a NUL-terminated string of wide (16-bit) characters and pushes its pointer onto the stack. |
B | PBYTE, PULONG, LPSTR, or LPWSTR | 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-printing characters.
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.
The buffer is meant to hold binary data, bytes from 0 - 255. If the data that is written to the buffer are ANSI characters, then they are NOT interpreted according to the system default Windows code page and any character whose code point is greater than 127 may be mapped to a different character in FMSLogo. Similarly, if the data that is written to the buffer are Unicode characters (LPWSTR), they are intepreted as if encoded in UTF-16LE (the low byte and the high byte of each WCHAR become two separate FMSLogo characters, with the character for the low byte first). |
If the optional dllname
input is given, then DLLCALL only looks for the function within that DLL.
The "B" argument types are returned as words of the exact length given. Any byte that is not overwritten by the function call is translated to NUL (the character whose code point is 0). So if the function fills in a string of bytes and only uses part of the buffer, the returned word will have a lot of zero characters 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 NUL characters 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 you 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.
The following example is equivalent to the C call:
MessageBox(NULL, L"Do you like FMSLogo?", L"Question", MB_YESNO);
Note how a "W" is added to the end of the name "MessageBox" and how the arguments are passed in reverse order to conform to the stdcall calling convention.
DLLLOAD "user32.dll IGNORE DLLCALL [L MessageBoxW L 4 U [Question] U [Do you like FMSLogo?] L 0]
See a message box pop up.
DLLFREE