Calling DLLs that return floats
by Richard Russell, May 2007, amended April 2013
BBC BASIC for Windows implements the SYS statement for calling routines in external DLLs (Dynamic Link Libraries). This statement has an optional TO clause which specifies a variable that should receive an integer value (if any) returned from the DLL:
SYS DLLfunction%, parameters TO result%
Here the variable result% receives the value returned from the DLL, which may be a result code (e.g. indicating success/failure), an integer numeric value or a pointer (e.g. to data in memory).
However very occasionally you may want to call a DLL function that returns a floating point value rather than an integer. You cannot do that directly using the SYS statement, but you can using the FN_sysfloat function listed later in this article. The syntax for that is as follows:
SYS FN_sysfloat(DLLfunction%, result#), parameters
Here the floating point value returned from the DLL is copied into the variable result#. Note that this variable must be able to accept a 64-bit double value, otherwise your program will most likely fail catastrophically! Hence either the variable name must have a # suffix or your program must run in the *FLOAT64 mode. Since it is acceptable to specify an explicit # suffix in both *FLOAT40 and *FLOAT64 modes this is the safest option.
Note that sometimes DLL functions return floating-point values in a different way: by requiring you to pass a pointer to a memory location at which the value will be stored. In that case the ordinary SYS statement can be used and there is no need to adopt the technique described in this article.
The FN_sysfloat function is listed below. It relies for its operation on undocumented internal behaviour of the BBC BASIC for Windows interpreter, so cannot be guaranteed to work with all future versions:
DEF FN_sysfloat(D%, RETURN R%) DIM R% LOCAL -1 PRIVATE A%, C%, S% IF A%=D% IF S%=R%!20 THEN =C% LOCAL P% IF C%=0 DIM C% 26 P% = C% : S% = R%!20 : A% = D% [OPT 2 pop dword [S%] call D% push dword [S%] fld st0 fstp qword [S%] ret ] =C%