Scripting Resources for DigitalMicrograph™ |
Example: Declaring Function Prototypes |
|
Function |
Demonstrates how to declare function prototypes. |
Version |
version:20130719, v1.0 |
Author |
D. R. G. Mitchell |
Acknowledgements |
- |
Comments |
A user-defined function must be declared before it can be called from within a script. One approach to this is to simply include all the functions' code at the start of the script and then have the main code follow with calls to the previously declared functions. I have written scripts this way for many years. However, this makes the main script appear at the end of the code when ideally it should be at the start, since casual readers are usually more interested in the main script rather than the functions - at least initially. This can be avoided by declaring function prototypes at the start of the script. Prototypes are a single line function declarations which include the following components: 1. The return type - what the function sends back when it is called such as a number, a string, an image or void if it returns nothing. 2. The function name. 3. The function variables in brackets and comma separated - what gets passed into the function such as number, image, string variables etc. 4. A terminating semicolon. Semicolons are required here. In C++ semicolons denote the end of each line of code.In DM script the only place they are required (that I have found to date) is in function prototype declarations. Note: Any number and type of variables can be passed into a function including numbers, images, strings etc, each separated by a comma. The function can not change the values of these passed in variables. Functions can return only one value via the return statement, which is limiting. However, passing in variables by reference allows the function to change the value of that variable. Any number of such variables can then be output from a function using this method. To identify a variable as being passed in by reference it has the & symbol in front of it. Such a variable must not be declared again within the function. |
System Requirements |
Should be compatible with all recent versions of DigitalMicrograph. |
Known Issues |
- |
Supported |
Yes |
Included Files |
Main script file. |
Source Code |
// Example script to show how to declare function prototypes. // D. R. G. Mitchell, adminnospam@dmscripting.com (remove the nospam to make this work) // version:20130719, v1.0, July 2013, www.dmscripting.com
// A function must be declared before it can be called from within a script. One approach to // this is to simply include all the functions' code at the start of the // script and then have the main code follow with calls to the previously declared functions. // I have done this for many years. However, this makes the main script appear at the end of the // code when ideally it should be at the start, since casual readers are // usually more interested in the main script than the functions - at least initially. // This can be avoided by declaring function prototypes at the start // of the script. These prototypes are a single line declarations // which include the following components:
// 1. The return type - what the function sends back when it is called // such as a number, a string or an image or void if it returns nothing. // 2. The function name. // 3. The function variables in brackets and comma separated - what gets passed into the function such as number etc. // 4. A terminating semicolon. Semicolons are required here. In C++ semicolons denote the end of each line of code. // In DM script the only place they are required (that I have found to date) is in function prototype declarations. // // Note: Any number and type of variables can be passed into a function including numbers, // images, strings etc, each separated by a comma. The function can not change the // values of these passed in variables. Functions can return only one value via the return statement, which // is limiting. However, passing in variables by reference allows the function to // change the value of that variable. Any number of such variables can then be output from a function using this method
// To identify a variable as being passed in by reference it has the & symbol in front of it. Such a variable must not // be declared again within the function.
// In the examples below the showmessage() function returns nothing (void) // it simply puts a message up on the screen.
// The second function calculatesquare() returns a number - the square of // the number passed into the function.
// The third function calculateroots() calculates both the square root and the cube root of the passed in number. // The square root is returned by the function in the normal way, while the cube root value // is output in a variable which has been passed in by reference.
// For this script declaring prototypes makes no immediate sense, but for // a large script with dozens of functions, containing thousands of lines // of code, it certainly helps.
// Declare function prototypes (remember to add the semicolons)
void showmessage(string whattosay); number calculatesquare(number valuetosquare); number calculateroots(number originalnumber, number &cuberoot);
// Main script starts here
number myvalue=9 string firstmessage="I am about to calculate the square of "+myvalue+"."
// Call the functions declared above as prototypes. The functions' definitions appear // at the end of the script
showmessage(firstmessage) // call the first function
// calculate the square of the number by calling the second function // and display the result by calling the first function again.
number sqrval=calculatesquare(myvalue) // call the second function string secondmessage="The square of "+myvalue+" is "+sqrval showmessage(secondmessage) // call the first function again
// Calculate the square root and cube root of the passed in number by calling the third function // and display the result by calling the first function again. Note the cuberoot variable is // passed into the function by reference. However, when it is called from within a script the & // symbol is not required. The & is only required in the declaration of the function. If it is also // declared as a prototype (as it is here), then the & needs to be used in the prototype declaration also.
number cuberoot number rootvalue=calculateroots(sqrval, cuberoot) // call the third function string thirdmessage="The square root of "+sqrval+" is "+rootvalue+". The cube root of "+sqrval+" is "+cuberoot+"." showmessage(thirdmessage) // call the first function again
// Main script ends here
// Function definitions start here
// First function which displays the passed in string on the screen
void showmessage(string message) { okdialog(message) // Since the function has void as the return type, this function returns // nothing, so there is no return statement. }
// Second function which calculates the square of the passed in number (valuetosquare)
number calculatesquare(number valuetosquare) { number sqrval=valuetosquare*valuetosquare return sqrval }
// Third function to calculate the square root of the number passed in (originalnumber). The function // also calculates the cube root value (the square root of the square root). However, since it // returns only one variable (here it is the square root), we use a variable passed in by reference // to get the cube root value out of the function. We define a passed in by reference variable with // the & symbol in front of it - in this case &cuberoot. It is essential that we do not // redeclare the cuberoot variable within the function, otherwise it will become a new variable which is // local to the function and the passed in by reference variable (&cuberoot) will always return 0.
number calculateroots(number originalnumber, number &cuberoot) { number squareroot=sqrt(originalnumber) // calculate the square root cuberoot=sqrt(squareroot) // the cube root - note the variable cuberoot is passed // in by reference (&cuberoot) and so MUST NOT be declared again within the body of the function // as number cuberoot=sqrt(squareroot) otherwise it becomes a completely new variable and // the &cuberoot value will always return 0. return squareroot }
|