私が行った読書によると、Core Audio はコールバック (および C++ ですが、それは別の話です) に大きく依存しています。
タスクを達成するために、別の関数によって繰り返し呼び出される関数をセットアップするという概念 (のようなもの) を理解しています。それらがどのようにセットアップされ、実際にどのように機能するかを理解していません。任意の例をいただければ幸いです。
C には「コールバック」はありません。他のジェネリック プログラミングの概念と同じです。
それらは関数ポインタを使用して実装されています。次に例を示します。
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
for (size_t i=0; i<arraySize; i++)
array[i] = getNextValue();
}
int getNextRandomValue(void)
{
return rand();
}
int main(void)
{
int myarray[10];
populate_array(myarray, 10, getNextRandomValue);
...
}
ここで、populate_array
関数は関数ポインターを 3 番目のパラメーターとして受け取り、それを呼び出して配列に入力する値を取得します。getNextRandomValue
ランダムっぽい値を返すcallback を書き、それへのポインタを に渡しましたpopulate_array
。populate_array
コールバック関数を 10 回呼び出し、返された値を指定された配列の要素に割り当てます。
C でのコールバックの例を次に示します。
イベントが発生したときに呼び出されるコールバックを登録できるコードを書きたいとしましょう。
最初に、コールバックに使用される関数のタイプを定義します。
typedef void (*event_cb_t)(const struct event *evt, void *userdata);
ここで、コールバックの登録に使用される関数を定義します。
int event_cb_register(event_cb_t cb, void *userdata);
コールバックを登録するコードは次のようになります。
static void my_event_cb(const struct event *evt, void *data)
{
/* do stuff and things with the event */
}
...
event_cb_register(my_event_cb, &my_custom_data);
...
イベント ディスパッチャーの内部では、コールバックは次のような構造体に格納される場合があります。
struct event_cb {
event_cb_t cb;
void *data;
};
コールバックを実行するコードは次のようになります。
struct event_cb *callback;
...
/* Get the event_cb that you want to execute */
callback->cb(event, callback->data);
簡単なコールバック プログラム。それがあなたの質問に答えることを願っています。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include "../../common_typedef.h"
typedef void (*call_back) (S32, S32);
void test_call_back(S32 a, S32 b)
{
printf("In call back function, a:%d \t b:%d \n", a, b);
}
void call_callback_func(call_back back)
{
S32 a = 5;
S32 b = 7;
back(a, b);
}
S32 main(S32 argc, S8 *argv[])
{
S32 ret = SUCCESS;
call_back back;
back = test_call_back;
call_callback_func(back);
return ret;
}
C のコールバック関数は、別の関数内で使用するために割り当てられた関数パラメーター/変数と同等です。ウィキの例
以下のコードでは、
#include <stdio.h>
#include <stdlib.h>
/* The calling function takes a single callback as a parameter. */
void PrintTwoNumbers(int (*numberSource)(void)) {
printf("%d and %d\n", numberSource(), numberSource());
}
/* A possible callback */
int overNineThousand(void) {
return (rand() % 1000) + 9001;
}
/* Another possible callback. */
int meaningOfLife(void) {
return 42;
}
/* Here we call PrintTwoNumbers() with three different callbacks. */
int main(void) {
PrintTwoNumbers(&rand);
PrintTwoNumbers(&overNineThousand);
PrintTwoNumbers(&meaningOfLife);
return 0;
}
関数呼び出し PrintTwoNumbers 内の関数 (*numberSource) は、実行時にコードによって指示されるように PrintTwoNumbers 内から「コールバック」/実行する関数です。
そのため、pthread 関数のようなものがあれば、そのインスタンス化からループ内で実行する別の関数を割り当てることができます。
C のコールバックは通常、関数ポインターと関連するデータ ポインターを使用して実装されます。on_event()
関数とデータ ポインターをフレームワーク関数に渡しますwatch_events()
(たとえば)。イベントが発生すると、データといくつかのイベント固有のデータを使用して関数が呼び出されます。
コールバックは、GUI プログラミングでも使用されます。GTK+ チュートリアルには、シグナルとコールバックの理論に関するすばらしいセクションがあります。
このウィキペディアの記事には、C の例があります。
良い例は、Apache Web サーバーを拡張するために作成された新しいモジュールが、関数ポインターを渡すことによってメインの apache プロセスに登録され、それらの関数が呼び出されて Web ページ要求を処理することです。
通常、これは、関数のメモリ位置を指す特別な変数である関数ポインタを使用して行うことができます。これを使用して、特定の引数で関数を呼び出すことができます。したがって、コールバック関数を設定する関数がおそらくあるでしょう。これは関数ポインタを受け入れ、そのアドレスを使用できる場所に保存します。その後、指定されたイベントがトリガーされると、その関数が呼び出されます。