'
' ------------------------------------------------------------------------
' MULTIPLE CALLBACK UNDER RAPIDQ Text Documentation by Jacques
'
' September 25rd, 2005
' August 13th, 2006
' This turn around was a group work. Thanks to John, Paul and Warriant
' ------------------------------------------------------------------------
'
' ------------------------------------------------------------------------
' A Short Example is Better than a long Theory for a Four Arguments CallBack
' The Extra Argument not counted
' ------------------------------------------------------------------------
' $Include "CallBack_4.Inc" ' _4 may be _0, _1, ..., _8 = Nbr of arguments of Your CallBack
'
' Function UserCallBackFunctionName (A1 As Long, A2 As Long, A3 as Long , A4 As Long) As Long
' ' nice efficient code
' End Function
'
' DefInt iAnyName
' Bind iAnyName To UserCallBackFunctionName ' iAnyName maybe reused but in some case not
' DefInt lpfnCallBack = SetNewCallBack_4 (iAnyName) ' _4 = Nbr of arguments of your CallBack
'
' ------------------------------------------------------------------------
' That's it
'
' CallBack_x.Inc automatically include CallBackForwarder.Inc if not yet included.
' LIMITATIONS :
' - _4 Can be _1, _2, _3, _4, _5, _6, _7, _8 for 1,2,3,4,4,6,7,8 Arguments
' - There is no maximum number of callback anymore
' - Any Use of the RapidQ CodePtr Word will DEEPLY harm this
' !!!!!!!!!! YOU CANNOT USE CODEPTR ANYMORE !!!!!!!!!!!!!
' RapidQ allows only one CodePtr for Each Function Prototype, if
' two CodePtr are used to point 4 arguments functions, the latter
' will overwrite the former (See CallBackBugDemo.Bas).
' ----------------------------------------------------------------------------------
' ----------------------------------------------------------------------------------
' HOW IT WORKS :
' ----------------------------------------------------------------------------------
' - the external process calls the CallBack Forwarder
' - the callback forwarder forwards the Caller to the master callback function
' (i.e MasterCallBack_4 in CallBack_4.Inc). It adds a first argument which is an
' the RapidQ handle of the RqFunction to forward to (Bind RqFuncHandle To YourCallBackFunc).
' - the master callback use CallFunc to Call the User CallBack. The Master Callback
' is built in the callback_X Include file.
'
' The Programmer Must (example for a 4 arguments CallBack):
' 1 - Get the RapidQ Function Handle of his CallBack Function
' DefInt hRqFunction
' Bind hRqFunction To RqCallBackFunction
' 2 - Create a CallBack Forwarder for his CallBack by calling
' lpfnCallBackForwarder = SetNewCallBack_4 (hRqFunction)
' lpfnCallBackForwarder returned by SetNewCallBack_4 is the address/lpfn
' you have to pass to the external process.
' **********************************************************************************
' ---- CallBack Forwader Documentation ---------------------------------------------
' The CallBack Forwarder Code (14 bytes) will be Generated in an allocated memory space,
' the pointer to that space is returned by the function.
' ForwardTo : a function pointer to our callback funtion (+ one one : first = CallBack
' Index you choose)
' CBIndex : a user choosen number to identify this CallBack forwarder
' --- CallBack Forwarder Nasm Assembler code ---- Nasm List ------------------------
' ----------------------------------------------------------------------------------
' Offset Hexadecimal Cycles Memory Mnemonic Comments
' decimal Code 486 CPU
' ----------------------------------------------------------------------------------
' 0000 58 1 1 pop eax ; eax = return address
' 0001 68DDCCBBAA 4 2 push dword CBIndex ; CBIndex 5th Argument
' 0005 50 1 1 push eax ; return address back on the stack
' 0007 B8DDCCBBAA 1 1 mov eax, ForwardTo ; eax = lpfnForwardTo
' 0012 FFE0 5 0 jmp eax ; Goto lpfnForwardTo
' ----------------------------------------------------------------------------------
' tot: 14 12 5
' ----------------------------------------------------------------------------------
' The job is done in 12 processor cycles and 5 memory access ! For a 2GHz processor
' it will take 6 billionth of a second + 5 memory access whose duration are unpredictable.
' ----------------------------------------------------------------------------------
' **********************************************************************************
'