コールバック手続き
記述:
出典: フリー百科事典『
ウィキペディア(Wikipedia)』
コールバック(英: Callback)とは、プログラミングにおいて、他のコードの引数として渡されるサブルーチンである。これにより、低レベルの抽象化層が高レベルの層で定義されたサブルーチン(または関数)を呼び出せるようになる。
一般に、まず高レベルのコードが低レベルのコードにある関数を呼び出すときに、別の関数へのポインタやハンドルを渡す。低レベルの関数を実行中に、その渡された関数を適当な回数呼び出して、部分タスクを実行する場合もある。別の方式では、低レベル関数は渡された関数を「ハンドラ」として登録し、低レベルの層で非同期的に(何らかの反応の一部として)後で呼び出すのに使う。
例:
数学関数(一次・二次関数、正弦関数)が、描画関数(PlotF)の引数となる例:
(呼び出しは 'PlotF()' 手続きを呼び出すことによって実装され、コールバック関数は 'Linear()', 'Sinusoidal()', 又は 'Quadratic()' 関数です)
Type MathFunction
As Function( ByVal x
As Double ) As Double
Function Linear
( ByVal x
As Double ) As Double
Return x
End Function
Function Quadratic
( ByVal x
As Double ) As Double
Return x * x
End Function
Function Sinusoidal
( ByVal x
As Double ) As Double
Return Sin(x
)
End Function
Sub PlotF
( ByVal f
As MathFunction
)
PSet( -
15, f
(-
15) )
For x
As Double = -
15 To 15 Step 0.1
Line -
( x, f
(x
) )
Next
End Sub
' Sets the graphics method GDI
' 描画方法を GDI に設定
SetEnviron("fbgfx=GDI")
Screen 19
Window (-
15,-
10)-
(15,
10)
PlotF
( @Linear
)
PlotF
( @Sinusoidal
)
PlotF
( @Quadratic
)
Sleep
注:FreeBASIC 1.08〜 で、SetEnviron を追加しなくても、日本語環境で描画画面が表示されるように改善されました。
3つのコールバック処理は同期的です。
'PlotF()' が呼び出し元のコードに戻る前に、各コールバック関数が完全に実行されるためです。
同様の描画例(上と同様)ですが、非同期コールバックを使います。
ここでは、人為的な遅延を加えています。
より現実的なケースは、描画されるデータが、プログラムのメインループで許容できるよりも長い応答時間で Webサーバーから取得される場合です(ブロッキング動作を防止します):
#Include
"fbthread.bi"
Type MathFunction
As Function( ByVal x
As Double ) As Double
Sub ThreadPlot
( ByVal p
As Any Ptr )
Sleep 1500,
1 '' sleep added only to check the asynchronous way of the callback
Dim f
As MathFunction = p
Window (-
15,-
10)-
(15,
10)
PSet( -
15, f
(-
15) )
For x
As Double = -
15 To 15 Step 0.1
Line -
( x, f
(x
) )
Next
End Sub
Function PlotF
( ByVal f
As MathFunction
) As String
Print "Plotting requested"
Threaddetach
( ThreadCreate( @ThreadPlot, f
) )
Return "Plotting request taken into account"
End Function
Function Linear
( ByVal x
As Double ) As Double
Return x
End Function
Function Quadratic
( ByVal x
As Double ) As Double
Return x * x
End Function
Function Sinusoidal
( ByVal x
As Double ) As Double
Return Sin(x
)
End Function
' Sets the graphics method GDI
' 描画方法を GDI に設定
SetEnviron("fbgfx=GDI")
Screen 19
Print PlotF
( @Linear
)
Print PlotF
( @Sinusoidal
)
Print PlotF
( @Quadratic
)
'' 以下のコードは呼び戻しの非同期性をチェックするためだけに追加
Print "Main program continues ";
For I
As Integer =
1 To 15
Print ".";
Sleep 200,
1
Next I
Print
Print "Main program finished"
Sleep
3つのコールバック処理は、非同期です。
これは、'PlotF()' 関数がすぐに戻り、それぞれのコールバック関数が 'PlotF()' によって(以前に)作成された 'ThreadPlot()' スレッドから、呼び出し元の次のコードと並行して実行されるからです。
qsort アルゴリズムでソートされる配列の値を比較する呼び戻し関数の例:
(呼び出しは 'qsort()' 手続きを呼び出すことによって実装され、コールバック関数は 'CmpVarLenStr()' 関数です)
#include "crt/stdlib.bi"
Function CmpVarLenStr CDecl( ByVal p1 As Any Ptr, ByVal p2 As Any Ptr ) As Long '' compare 2 var-len strings
Dim As String Ptr ps1 = p1
Dim As String Ptr ps2 = p2
If *ps1 < *ps2 Then
Return -1
ElseIf *ps1 > *ps2 Then
Return 1
Else
Return 0
End If
End Function
Sub PrintList( array() As String) '' print a var-len string list
For I As Integer = LBound(array) To UBound(array)
Print array(I)
Next I
Print
End Sub
Dim forename(1 To 12) As String = {"Madison", "Emily", "Hailey", "Sarah", "Kaitlyn", "Hannah", _
"Jacob", "Christopher", "Nicholas", "Michael", "Matthew", "Joshua" }
Print "LIST OF UNSORTED FORENAMES:"
PrintList( forename() )
qsort( @forename(LBound(forename)), UBound(forename) - LBound(forename) + 1, SizeOf(String), @CmpVarLenStr )
Print "LIST OF SORTED FORENAMES:"
PrintList( forename() )
Sleep
コールバック関数は完全に(数回)実行され、'qsort()' が呼び出し元のコードに戻る前に 'qsort()' によって(連続して)呼び出されるため、コールバックプロセスは同期的です。
参照: