User Tools

Site Tools


passing_20floating-point_20values_20to_20dlls

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
passing_20floating-point_20values_20to_20dlls [2018/03/31 13:19] – external edit 127.0.0.1passing_20floating-point_20values_20to_20dlls [2024/01/05 00:21] (current) – external edit 127.0.0.1
Line 3: Line 3:
 //by Richard Russell, July 2009//\\ \\  The majority of functions that you are likely to want to call using [[http://www.bbcbasic.co.uk/bbcwin/manual/bbcwin7.html#sys|SYS]] (typically Windows API functions, or functions in third-party DLLs) will require only **integer** or **string** parameters; you can specify those straightforwardly in the **SYS** statement.\\ \\  Occasionally, however, you may need to pass a floating-point parameter to such a function. Unfortunately you cannot usually do that simply by including the appropriate variable or constant in the **SYS** statement; this article describes what you need to do instead.\\ \\  There are two main ways of passing floating-point parameters: **by reference** or **by value**. In the first case you pass a **pointer** to the floating-point value (the memory address at which it is stored), and in the second case you pass the **value** itself. There are also (principally) two different types of floating-point value that the function may require: a 32-bit **float** value or a 64-bit **double** value.\\ \\  You must first ascertain from the documentation of the function whether the parameter is to be passed **by reference** or **by value**, and whether the parameter needs to be a **float** or a **double**; this is vitally important!\\ \\  Below are listed the methods you must adopt in each of the four possible circumstances:\\ \\  //by Richard Russell, July 2009//\\ \\  The majority of functions that you are likely to want to call using [[http://www.bbcbasic.co.uk/bbcwin/manual/bbcwin7.html#sys|SYS]] (typically Windows API functions, or functions in third-party DLLs) will require only **integer** or **string** parameters; you can specify those straightforwardly in the **SYS** statement.\\ \\  Occasionally, however, you may need to pass a floating-point parameter to such a function. Unfortunately you cannot usually do that simply by including the appropriate variable or constant in the **SYS** statement; this article describes what you need to do instead.\\ \\  There are two main ways of passing floating-point parameters: **by reference** or **by value**. In the first case you pass a **pointer** to the floating-point value (the memory address at which it is stored), and in the second case you pass the **value** itself. There are also (principally) two different types of floating-point value that the function may require: a 32-bit **float** value or a 64-bit **double** value.\\ \\  You must first ascertain from the documentation of the function whether the parameter is to be passed **by reference** or **by value**, and whether the parameter needs to be a **float** or a **double**; this is vitally important!\\ \\  Below are listed the methods you must adopt in each of the four possible circumstances:\\ \\ 
 ==== 64-bit doubles passed by reference ==== ==== 64-bit doubles passed by reference ====
-\\  This is the simplest case to deal with in BB4W. Suppose you want to pass the variable **fpv**:\\ \\ +\\  This is the simplest case to deal with in BB4W. Suppose you want to pass the variable **fpv**: 
 + 
 +<code bb4w>
         fpv# = fpv * 1.0#         fpv# = fpv * 1.0#
         SYS "FunctionName", ^fpv#         SYS "FunctionName", ^fpv#
-Here the value is converted (if necessary) to a 64-bit float (by multiplying it by **1.0#**) and then stored in the 64-bit variable **fpv#**. The parameter supplied in the SYS call is the address of the variable (**^fpv#**).\\ \\  Rather than a scalar value, you may need to pass an **array** of values (arrays are invariably passed by reference). You can do that in a similar way, for example to pass the array **fpv#()**:\\ \\ +</code> 
 + 
 +Here the value is converted (if necessary) to a 64-bit float (by multiplying it by **1.0#**) and then stored in the 64-bit variable **fpv#**. The parameter supplied in the SYS call is the address of the variable (**^fpv#**).\\ \\  Rather than a scalar value, you may need to pass an **array** of values (arrays are invariably passed by reference). You can do that in a similar way, for example to pass the array **fpv#()**: 
 + 
 +<code bb4w>
         fpv#() *= 1.0#         fpv#() *= 1.0#
         SYS "FunctionName", ^fpv#(0)         SYS "FunctionName", ^fpv#(0)
-Here it is assumed that the array was originally declared with 64-bit elements (i.e. either in ***FLOAT 64** mode or by explicitly specifying a **#** suffix).\\ \\  If your array uses suffices starting at **1** rather than 0 then you will need to pass the address of the base element:\\ \\ +</code> 
 + 
 +Here it is assumed that the array was originally declared with 64-bit elements (i.e. either in ***FLOAT 64** mode or by explicitly specifying a **#** suffix).\\ \\  If your array uses suffices starting at **1** rather than 0 then you will need to pass the address of the base element: 
 + 
 +<code bb4w>
         fpv#() *= 1.0#         fpv#() *= 1.0#
         SYS "FunctionName", ^fpv#(1)         SYS "FunctionName", ^fpv#(1)
-\\ +</code> 
 ==== 64-bit doubles passed by value ==== ==== 64-bit doubles passed by value ====
-\\  Since each parameter of the **SYS** statement is passed as a 32-bit value, a 64-bit floating-point value must be passed as **two** parameters. Suppose you want to pass the variable **fpv**:\\ \\ +\\  Since each parameter of the **SYS** statement is passed as a 32-bit value, a 64-bit floating-point value must be passed as **two** parameters. Suppose you want to pass the variable **fpv**: 
 + 
 +<code bb4w>
         SYS "FunctionName", FN_dl(fpv), FN_dh(fpv)         SYS "FunctionName", FN_dl(fpv), FN_dh(fpv)
-The 'helper functions' **FN_dl** and **FN_dh** are listed [[/Passing%20floating-point%20values%20to%20DLLs#helpers|below]]. If you prefer to use 'inline' code rather than call the helper functions you can do that as follows:\\ \\ +</code> 
 + 
 +The 'helper functions' **FN_dl** and **FN_dh** are listed [[/Passing%20floating-point%20values%20to%20DLLs#helpers|below]]. If you prefer to use 'inline' code rather than call the helper functions you can do that as follows: 
 + 
 +<code bb4w>
         fpv# = fpv * 1.0#         fpv# = fpv * 1.0#
         SYS "FunctionName", !^fpv#, !(^fpv#+4)         SYS "FunctionName", !^fpv#, !(^fpv#+4)
-\\ +</code> 
 ==== 32-bit floats passed by reference ==== ==== 32-bit floats passed by reference ====
-\\  BBC BASIC for Windows doesn't have a native 32-bit float type, so a conversion is required. Suppose you want to pass the variable **fpv** by reference:\\ \\ +\\  BBC BASIC for Windows doesn't have a native 32-bit float type, so a conversion is required. Suppose you want to pass the variable **fpv** by reference: 
 + 
 +<code bb4w>
         temp% = FN_f4(fpv)         temp% = FN_f4(fpv)
         SYS "FunctionName", ^temp%         SYS "FunctionName", ^temp%
 +</code>
 +
 Here the temporary variable **temp%** is loaded with the 32-bit float, and then its address is passed as the parameter.\\ \\  Here the temporary variable **temp%** is loaded with the 32-bit float, and then its address is passed as the parameter.\\ \\ 
 ==== 32-bit floats passed by value ==== ==== 32-bit floats passed by value ====
-\\  This is similar to the previous case, except that the temporary variable is not required. So to pass the variable **fpv** by value:\\ \\ +\\  This is similar to the previous case, except that the temporary variable is not required. So to pass the variable **fpv** by value: 
 + 
 +<code bb4w>
         SYS "FunctionName", FN_f4(fpv)         SYS "FunctionName", FN_f4(fpv)
 +</code>
 +
 The 'helper function' **FN_f4** is listed [[/Passing%20floating-point%20values%20to%20DLLs#helpers|below]].\\ \\  The 'helper function' **FN_f4** is listed [[/Passing%20floating-point%20values%20to%20DLLs#helpers|below]].\\ \\ 
 ==== Helper functions ==== ==== Helper functions ====
-\\ Here are the functions used in the above examples:\\ \\  +\\ Here are the functions used in the above examples: 
-        REM Convert to 64-bit double (low 4 bytes) + 
-        DEF FN_dl(A#) +<code bb4w> 
-        A# *= 1.0# +      REM Convert to 64-bit double (low 4 bytes) 
-        = !^A#+      DEF FN_dl(A#) 
 +      A# *= 1.0# 
 +      = !^A#
  
-        REM Convert to 64-bit double (high 4 bytes) +      REM Convert to 64-bit double (high 4 bytes) 
-        DEF FN_dh(A#) +      DEF FN_dh(A#) 
-        A# *= 1.0# +      A# *= 1.0# 
-        = !(^A#+4)+      = !(^A#+4)
  
-        REM Convert to 32-bit float +      REM Convert to 32-bit float 
-        DEF FN_f4(A#) +      DEF FN_f4(a#)LOCALP%:P%=^a#:IFABSa#<1E-38 THEN=FALSE 
-        LOCAL A%,P+      =P%!4 AND NOT&7FFFFFFFOR(P%!4-&38000000<<3 OR!P%>>29 AND7)+(!P%>>28 AND1) 
-        PRIVATE F% +</code>
-        IF F%=THEN +
-          DIM P%10 +
-          [OPT 2 +
-          .F% +
-          mov esi,[ebp+2]:mov edi,[ebp+7] +
-          fld qword [esi]:fstp dword [edi] +
-          ret +
-          ] +
-        ENDIF +
-        A# *= 1.0# +
-        CALL F%,A#,A+
-        =A%+
passing_20floating-point_20values_20to_20dlls.1522502372.txt.gz · Last modified: 2024/01/05 00:17 (external edit)