Я думаю, что получил ответ.
Реальная проблема заключается в получении указателя контекста 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 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 до пары тысяч. Затем мне нужно будет отследить, какие функции уже зарегистрированы, а какие нет, и предоставить некоторый механизм для выбора следующих доступных и освобождения тех, которые больше не нужны.