在C语言中,将函数指针用作来自某些库的回调的常用方法是为用户上下文添加void*
指针:
void (*fp)(void* ctx);
这允许库使用上下文ctx
调用回调。
假设我使用的库在回调中不包含上下文指针。我需要为每个上下文提供一个回调。在C中动态分配函数指针以提供回调的最便捷方法是什么?我如何malloc()
可以从库中调用的功能代码?
例如:
typedef void (*my_fp_t)(char);
my_fp_t fp = (my_fp_t) malloc(sizeof(...));
init_function_ptr(fp, "Hello, there");
my_library_callback(fp);
...
void my_library_callback(my_fp_t fp) {
fp('a'); // prints "Hello, there"
}
答案 0 :(得分:2)
假设您希望分配实际的功能代码,而不是功能指针。编写引导加载程序和类似内容时的完成方式:
#pragma __declspec __attribute__
等等,上面放糖。高度特定于编译器。uint8_t func [n]
数组分配给该区域,以十六进制形式包含原始OP代码。((func_ptr)func) ()
调用代码。如您所愿,根据系统的不同,这可能是一项艰巨的任务。对于使用嵌入式系统编译器的小型微控制器,这在某种程度上很容易实现。对于诸如x86或PowerPC之类的更复杂的系统,使用诸如gcc之类的编译器,要少得多。您将依靠各种错误指定的行为,并且代码将完全是特定于系统的。
答案 1 :(得分:0)
我想我得到了答案。
真正的问题是在一个没有收到回调的回调中获取void*
上下文指针。而且我不能使用(原则上)全局变量,因为可能会调用许多回调,而且我无法确定是哪一个。
我可以采取与JIT VM相同的方法:为每个可能的void * ctx值动态生成机器代码,例如:
void do_stuff(void* ctx) {
// Finally have the ctx!
}
void* my_ctx;
my_fn_ptr p = allocate_function_that_calls_f_with_ctx(do_stuff, ctx);
library_register_callback_fn(p);
这里p
是带有签名void (*)(void)
的函数的函数指针,当依次调用时,它将调用f(ctx)
。
但是,这仅用于库的回调,并且回调的数量很少。然后,我可以编写一堆函数,每个函数取一个表中的void *,每个函数取自不同的索引:
void do_stuff_0(void) { do_stuff(do_stuff_TABLE[0]); }
void do_stuff_1(void) { do_stuff(do_stuff_TABLE[1]); }
void do_stuff_2(void) { do_stuff(do_stuff_TABLE[2]); }
...
我可以编写一些简单的脚本,在新的.c文件中写入从0到成千上万的所有函数。然后,我需要跟踪已注册的功能和尚未注册的功能,并提供某种机制以选择下一个可用功能并释放不再需要的功能。