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:

code format="bb4w" SYS DLLfunction%, parameters TO result% code 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:

code format="bb4w" SYS FN_sysfloat(DLLfunction%, result#), parameters code 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:

code format="bb4w" 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% code