C言語教室 第25回 - コールバック関数
コールバックという言葉は元々は電話を掛けた時に、こちらの電話番号などの情報を伝えて、相手方から掛け直してもらうことを指します。この言葉がプログラムで使われる時には、呼び出す関数に引き数で関数の情報を渡し、呼び出した関数で呼んでもらうという時に、渡す関数のことをコールバック関数と言います。
コールバック (情報工学)
このWikiの説明で何を言っているかが判るのは、既にコールバック関数のことを理解している人だけかもしれませんが、要は関数呼び出しの引き数で関数を渡すということです。
この方法が使えないと、呼び出した関数で処理を切り替えて欲しい時には、引き数で番号なりで処理の種類を伝えて、呼び出した関数の中で、その番号に応じた関数を呼び出すということが精一杯で、この場合は予め呼び出す関数の中に、さらに呼び出してもらう関数の名前をすべて列挙しておく必要があります。もし呼び出してもらう関数に変更がある場合は、名前を変更してコンパイルし直す必要があります。こうなるとライブラリの中に置くことは難しくなります。
まあ、そんなコトをしなくても何とかなると思うかもしれませんが、呼び出した関数のループの中などで呼び出す関数を切り替えたいことは、それなりに発生して、関数を分割すると、途中まで処理した「状態」をやりとりする必要が出て、なかなか面倒なことになりがちです。
また、わざわざ必要性に迫られなくても、signalなどのライブラリ関数を使おうとすると、このコールバック関数が必要になるので、仕方なく覚える羽目になります。
signal
C言語のプログラムであっても、入力がキーボード(標準入力)に接続している限り、CTRL-Cなどで停止することも出来るのですが、ファイルを読み書きしている最中などに止められてしまうのは困ることもあります。こういう時には、シグナルハンドラと呼ばれる CTRL-Cが入力された時に実行する関数を用意します。
[ C言語 ] 「Ctrl + C」 でプログラムを終了させないようにする ( SIGINT )
シグナルは他にもいろいろな理由で発生するので、業務向けのプログラムであれば、ちゃんと処理しておくのが礼儀というものです。
signal() - 割り込みの処理
また非同期処理を行う場合には、コールバック関数の仕組みが必須になるのですが、そちらはスレッドを使う場合が殆どなので割愛しますが、スレッドを使わなくてもネットワークやファイル、パイプなどで他のプロセスと通信するとコールバック関数が登場することがあります。
他にも引き数の型が違っても同じ処理がしたい時に、C言語では関数の多重定義も出来ませんので、型チェックを回避し引き数に型に応じた関数を渡すことで処理をまとめてしまうというテクニックを使うこともあります。他の言語であればバリアント型で渡すときにような使い方ですね。
関数ポインタ自身も、まだシックリ来ていない方も多いようなので、これらを説明しているページを紹介しておきます。
C言語の関数ポインタについて解説
Callback関数を知らん人がまず理解すべきことのまとめ。
コールバック関数とは
以下のページはコールバック関数として、今後の教室で取り上げるつもりのソートに関するコードも記載されています。
第3章 関数を指すポインタ
そういえば最近は signal ではなく sigaction が推奨されているようです。ちゃんと知識をアップデートしておかないとですね。
【C言語】signalとsigactionの使い方を分かりやすく解説(実装サンプルあり)
この課題は環境を選ぶかもしれないので、うまく確かめられない環境の場合は、コールバック関数を使う例を書いていただくのでも構いません。
ヘッダ画像は、いらすとや より
https://www.irasutoya.com/2014/01/blog-post_1810.html