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

passing_20floating-point_20values_20to_20dlls [2018/03/31 13:19]
127.0.0.1 external edit
passing_20floating-point_20values_20to_20dlls [2018/04/14 17:13] (current)
richardrussell Added syntax highlighting
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.txt · Last modified: 2018/04/14 17:13 by richardrussell