Function Pointer

Data type that stores a pointer to a Function procedure returning a value

Syntax
   Dim variable As Function [cdecl|pascal|stdcall] [( [parameter_list] )] [ 
   ByRef ] [As return_type] [= initializer]

Parameters
   parameter_list: parameter[, parameter[, ...]]
   parameter: [ByRef|ByVal] identifier [As type] [= default_value]
      identifier: the name of the variable referenced in the function
      type: the type of variable
      default_value: the value of the argument if none is specified in the 
      call
   return_value: the value returned from the function
   intializer: address of a function to set as the initial value

Description
   A Function pointer is a procedure pointer that stores the memory 
   location of compiled code that returns a value.  If no intializer is 
   given the default initial value is zero (0).

   The memory address for the Function procedure can be assigned to the 
   variable by taking the address of a function with ProcPtr or 
   Operator @ (Address Of).

   The procedure must match the same Function declaration as the declared 
   Function pointer.

   To call the function assigned, use the variable name as if it were a 
   normal declared Function, always with parentheses around the parameter 
   list even empty (without parentheses, only the pointer value, ie the 
   address of the function, would be accessed).

   One of the primary uses for Function pointers is to create callback 
   procedures:
      - A callback Function is a Function that is passed through an 
      argument (a Function pointer) to another procedure which is expected 
      to call back (execute) the "argument" at a convenient time.
      - If the callback Function is completely executed before the 
      invocation returns to the caller code, then the callback process is 
      said to be "synchronous".
      - If the invocation immediately returns to the caller code, and the 
      callback Function and the caller's next code are running in parallel, 
      then the callback process is said to be "asynchronous".

Example
   Function ConcatSelf( x As String ) As String
      Return x & x
   End Function

   Dim x As Function( x As String ) As String = ProcPtr( ConcatSelf )

   Print x( "Hello" )

   Function x2 (ByVal i As Integer) As Integer
     Return i * 2
   End Function

   Function x3 (ByVal i As Integer) As Integer
     Return i * 3
   End Function

   Function operation (ByVal i As Integer, ByVal op As Function (ByVal As Integer) As Integer) As Integer
     Return op(i)
   End Function

   Print operation(4, @x2)
   Print operation(4, @x3)

   ' Example of basic callback Function mechanism (asynchronous) to implement a key pressed event:
   ' (the user callback Function address cannot be modified while the event thread is running)
   '   - An asynchronous thread tests the keyboard in a loop, and calls a user callback Function each time a key is pressed.
   '   - The callback Function address is passed to the thread.
   '   - The callback Function prints the character of the key pressed,
   '       but if the key pressed is <escape> it orders the thread to finish by using the function return value.
   '   - As the user callback address is passed to the thread as argument, it cannot be modified while the thread is running.

   '' thread Sub definition
     Sub threadInkey (ByVal p As Any Ptr)
      If p > 0 Then                                                '' test condition callback Function defined
        Dim As Function (ByRef As String) As Integer callback = p  '' convert the any ptr to a callback Function pointer
        Do
         Dim As String s = Inkey
         If s <> "" Then                                          '' test condition key pressed
           If callback(s) Then                                    '' test condition to finish thread
            Exit Do
           End If
         End If
         Sleep 50, 1
        Loop
      End If
     End Sub

   '' user callback Function definition
     Function printInkey (ByRef s As String) As Integer
      If Asc(s) = 27 Then                                        '' test condition key pressed = <escape>
        Print
        Return -1                                                '' order thread to finish
      Else
        Print s;
        Return 0                                                 '' order thread to continue
      End If
     End Function

   '' user main code
     Dim As Any Ptr p = ThreadCreate(@threadInkey, @printInkey)   '' launch the thread, passing the callback Function address
     ThreadWait(p)                                                '' wait for the thread finish

Differences from QB
   * New to FreeBASIC

See also
   * Function
   * ProcPtr
   * Operator @ (Address Of)

