将来のある時点で呼び出されるコールバック (関数ポインタ) を引数として受け入れるライブラリ関数 (変更できない) があるとします。私の質問: コールバックが呼び出されたときに余分なデータを取得できるように、関数ポインターと共に余分なデータを格納する方法はありますか? プログラムはcです。
例えば:
// callback's type, no argument
typedef void (*callback_t)();
// the library function
void regist_callback(callback_t cb);
// store data with the function pointer
callback_t store_data(callback_t cb, int data);
// retrieve data within the callback
int retrieve_data();
void my_callback() {
int a;
a = retrieve_data();
// do something with a ...
}
int my_func(...) {
// some variables that i want to pass to my_callback
int a;
// ... regist_callback may be called multiple times
regist_callback(store_data(my_callback, a));
// ...
}
問題は、callback_tが引数を受け入れないためです。私の考えは、regist_callback に入力するたびに小さな asm コードを生成することです。それが呼び出されると、実際のコールバックとそのデータを見つけてスタック (または未使用のレジスタ) に格納し、実際のコードにジャンプします。コールバック内で、データを見つけることができます。
疑似コード:
typedef struct {
// some asm code knows the following is the real callback
char trampoline_code[X];
callback_t real_callback;
int data;
} func_ptr_t;
callback_t store_data(callback_t cb, int data) {
// ... malloc a func_ptr_t
func_ptr_t * fpt = malloc(...);
// fill the trampoline_code, different machine and
// different calling conversion are different
// ...
fpt->real_callback = cb;
fpt->data = data;
return (callback_t)fpt;
}
int retrieve_data() {
// ... some asm code to retrive data on stack (or some register)
// and return
}
それは合理的ですか?そのような問題に対して行われた以前の作業はありますか?