假設存在一個庫函數(無法修改),它接受一個回調(函數指針)作爲它的參數,這個函數將在未來的某個時刻被調用。我的問題:是否有一種方法可以將額外的數據與函數指針一起存儲,以便在調用回調函數時可以檢索額外的數據。該計劃在c。在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接受任何參數。我的想法是每次生成一小段asm代碼以填充regist_callback,當它被調用時,它可以找到真正的回調函數和它的數據並將其存儲在堆棧(或一些未使用的寄存器)上,然後跳轉到真實回調,並在回調中,可以找到數據。
僞代碼:
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
}
是否合理?以前有沒有爲這個問題做過工作?
爲什麼不讓store_date()在全局映射中存儲原函數的地址以及對'a'的引用並通過'retrieve_data()'檢索? – alk
如果多次註冊相同的回調,當回調被調用時,它不知道哪一個回調。 – jayven
是的,這個用例不能用這種方式來覆蓋。但是,您可以通過爲每個同時註冊的實例實現包裝來解決此問題。或者只是使用cb函數地址的一些未使用的低位(或甚至高位)位來添加子索引... - 8字節指針很寬;-) – alk