Предположим, у меня есть алгоритм, который принимает обратный вызов:
void algorithm(void (*callback)()){
(*callback)(a,b,c);
}
Я думаю, что это требует от меня объявить глобальную функцию для каждого другого поведения, что я для обратного вызова.
A лучше, более общий интерфейс может быть:
void algorithm(void (*callback)(), void* cbdata, <...some parameter...>){
(*callback)(cbdata, a,b,c);
}
... теперь я могу реализовать все виды поведения, и мне не нужно определять новую функцию для каждого. Например, cbdata может быть указателем на структуру данных экземпляра + метода C ++, и обратный вызов вызывает этот метод вместе с экземпляром. Этот экземпляр C ++ теперь может обеспечить все виды поведения для обратного вызова.
Однако, к сожалению, у нас может быть интерфейс, который нам дан, а не тот, который мы хотим.
void algorithm(void (*callback)(), <...some parameter...>){
(*callback)(a,b,c);
}
. .. у нас нет слота для предоставления cbdata
нашему обратному вызову.
На других языках просто сократить вызов функции с параметрами до одного с меньшим количеством параметров с замыканиями. Как это можно сделать в C? Интерфейс принимает один обратный вызов, но я не хочу реализовывать библиотечную функцию для каждого поведения - я бы хотел, скажем, определить одну функцию, которая может реализовывать много поведений.
Я нашел Достижение закрытия в C, но оно страдает от проблем, связанных с тем, что «параметр закрытия» хранится в стеке:
int main(void) {
struct ClosureData* cbdata;
...
int callback(int a, int b, int c) {
...
cbdata->method(cbdata->self);
...
};
algorithm(&callback);
}
Это может быть неудобно, если мы хотим установить обратные вызовы в инициализация библиотеки и возврат из функции инициализации.
Поскольку C обратные вызовы являются указателем на (C соглашение о вызове) код, который должен быть выполнен, я думаю, что нам понадобится новый указатель на новый код. Итак ... возможно ли, что в работающей программе я могу «создать» новую программную память, в которую я могу поместить ссылку на свои данные, а затем получить указатель на функцию?
Это кажется трудным, но не невозможным. Загрузка разделяемой библиотеки / DLL подразумевает добавление новых ссылочных участков кода во время работы программы.