Добрый день.
Вопрос:
Пишем глобальную callback-функцию. Студия ругается при попытке вызова моей функции:
cannot covert parametr ... to 'void (__cdecl *)(void)'
Слишком сложно для понимания.
1. Как-то можно упростить приведенную конструкцию?
2. Как должен выглядеть прототип моей callback-функции при таком требовании к "входящему параметру"?
Здравствуйте, Jumangee, Вы писали:
J>cannot covert parametr ... to 'void (__cdecl *)(void)' J>1. Как-то можно упростить приведенную конструкцию?
Вставь имя переменной в декларатор, если не понимаешь.
Тут будет так:
void (__cdecl*f)(void), то есть f -- это указатель на функцию.
Ну а сама функция должна быть
void __cdecl f(void)
J>2. Как должен выглядеть прототип моей callback-функции при таком требовании к "входящему параметру"?
Вообще в С/С++ действует правило "декларатор выглядит как пример использования)
(void) -- Это С-шная штука, в С++ она эквивалентна просто отсутствию аргументов ()
То есть void (*f)() надо понимать так, что если f разыменовть (*f), и потом вызвать без аргументов
(*f)(), то получится void.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Jumangee, Вы писали:
J>Тема больше не актуальна.
И всё же, вдогонку, скажу.
Очень часто требуется, чтобы колбек был с контекстом. Таким контекстом может стать объект, чей метод собрались вызвать, или какие-то связанные параметры...
Поэтому, когда проектируется API, принимающий колбеки, то это пожелание учитывается.
Либо в чисто сишном стиле — колбеком является пара (функция, обезличенный аргумент контекста — intptr_t / void*).
Либо в плюсовом — колбеком является std::function, которую строят из лямбды или std::bind.
Либо проблема решается на клиентской стороне:
— на лету строится исполнимый код, который для вызывающей стороны является функцией без контекста, а внутри — вызывает целевую функцию со связанными и свободными параметрами.
— заводится пул функций и параллельно — статический массив контекстов; положили нужное значение в свободную ячейку и отдали указатель на соответствующую этой ячейке функцию.
Для непортабельного кода на MFC/ATL/WTL вариант с кодогенерацией был доступен из коробки (кажется, <atlthunk.h>). Хотя это и плохая практика.
Здравствуйте, уважаемый Кодт, Вы писали:
К>Либо в плюсовом — колбеком является std::function, которую строят из лямбды или std::bind.
Я видел информацию, что вариант от boost (т.е. boost::function) — оказывается эффективнее http://stackoverflow.com/questions/7852101/c-lambda-with-captures-as-a-function-pointer
не проверял, т.к. пользуюсь:
std::function
Есть ли какие-то соображения насчёт применения boost::function вместо std::function?