假设有一个库函数(不能修改)接受一个回调(函数指针)作为它的参数,将在未来的某个时刻被调用。我的问题是:有没有办法将额外的数据与函数指针一起存储,这样当调用回调时,可以检索额外的数据。该计划在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
}
合理吗?以前的工作是否有过这样的问题?
答案 0 :(得分:2)
不幸的是,随着时间的推移,您可能会被禁止在越来越多的系统中执行蹦床,因为执行数据是利用安全漏洞的一种非常常见的方式。
我首先将错误报告给库的作者。每个人都应该知道比提供没有私有数据参数的回调接口更好。
有这样的限制会让我三思而后行,图书馆是否可以重入。我建议确保一次只能有一个未完成的调用,并将回调参数存储在全局变量中。
如果您认为该库适合使用,那么您可以通过编写n
个不同的回调蹦床来扩展它,每个回调蹦床都引用它们自己的全局数据,并将其包装在一些管理API中。