Windows callback function c

Callback Functions

A callback function is code within a managed application that helps an unmanaged DLL function complete a task. Calls to a callback function pass indirectly from a managed application, through a DLL function, and back to the managed implementation. Some of the many DLL functions called with platform invoke require a callback function in managed code to run properly.

To call most DLL functions from managed code, you create a managed definition of the function and then call it. The process is straightforward.

Using a DLL function that requires a callback function has some additional steps. First, you must determine whether the function requires a callback by looking at the documentation for the function. Next, you have to create the callback function in your managed application. Finally, you call the DLL function, passing a pointer to the callback function as an argument.

The following illustration summarizes the callback function and implementation steps:

Callback functions are ideal for use in situations in which a task is performed repeatedly. Another common usage is with enumeration functions, such as EnumFontFamilies, EnumPrinters, and EnumWindows in the Windows API. The EnumWindows function enumerates through all existing windows on your computer, calling the callback function to perform a task on each window. For instructions and an example, see How to: Implement Callback Functions.

WindowProc callback function

An application-defined function that processes messages sent to a window. The WNDPROC type defines a pointer to this callback function.

WindowProc is a placeholder for the application-defined function name.

Syntax

Parameters

hwnd [in]
Type: HWND

A handle to the window.

uMsg [in]
Type: UINT

For lists of the system-provided messages, see System-Defined Messages.

wParam [in]
Type: WPARAM

Additional message information. The contents of this parameter depend on the value of the uMsg parameter.

lParam [in]
Type: LPARAM

Additional message information. The contents of this parameter depend on the value of the uMsg parameter.

Return value

The return value is the result of the message processing and depends on the message sent.

Remarks

If your application runs on a 32-bit version of Windows operating system, uncaught exceptions from the callback will be passed onto higher-level exception handlers of your application when available. The system then calls the unhandled exception filter to handle the exception prior to terminating the process. If the PCA is enabled, it will offer to fix the problem the next time you run the application.

However, if your application runs on a 64-bit version of Windows operating system or WOW64, you should be aware that a 64-bit operating system handles uncaught exceptions differently based on its 64-bit processor architecture, exception architecture, and calling convention. The following table summarizes all possible ways that a 64-bit Windows operating system or WOW64 handles uncaught exceptions.

Behavior type How the system handles uncaught exceptions
1 The system suppresses any uncaught exceptions.
2 The system first terminates the process, and then the Program Compatibility Assistant (PCA) offers to fix it the next time you run the application. You can disable the PCA mitigation by adding a Compatibility section to the application manifest.
3 The system calls the exception filters but suppresses any uncaught exceptions when it leaves the callback scope, without invoking the associated handlers.

The following table shows how a 64-bit version of Windows operating system or WOW64 handles uncaught exceptions. Notice that behavior type 2 only applies to the 64-bit version of the Windows 7 operating system.

Operating System WOW64 64-bit Windows
Windows XP 3 1
Windows Server 2003 3 1
Windows Vista 3 1
Windows Vista SP1 1 1
Windows 7 and later 1 2

NoteВ В On Windows 7 with SP1 (32-bit, 64-bit or WOW64), the system calls the unhandled exception filter to handle the exception prior to terminating the process. If the PCA is enabled, it will offer to fix the problem the next time you run the application.

If you need to handle exceptions in your application, you can use structured exception handling to do so. For more information on how to use structured exception handling, see Structured Exception Handling.

Requirements

Minimum supported client

WindowsВ 2000 Professional [desktop apps only]

Функции обратного вызова Callback Functions

Функция обратного вызова — это программный код в управляемом приложении, который помогает неуправляемой функции DLL выполнить задачу. A callback function is code within a managed application that helps an unmanaged DLL function complete a task. Вызовы функции обратного вызова косвенно, через функцию DLL, передаются из управляемого приложения и возвращаются в управляемую реализацию. Calls to a callback function pass indirectly from a managed application, through a DLL function, and back to the managed implementation. Лишь некоторые из многих функций DLL, вызываемых в вызове неуправляемого кода, требуют для своего выполнения наличия в управляемом коде функции обратного вызова. Some of the many DLL functions called with platform invoke require a callback function in managed code to run properly.

Для вызова большинства функций DLL из управляемого кода нужно создать управляемое определение функции и затем выполнить сам вызов. To call most DLL functions from managed code, you create a managed definition of the function and then call it. Этот процесс достаточно прост. The process is straightforward.

Применение функции DLL, требующей наличия функции обратного вызова, предполагает выполнение некоторых дополнительных шагов. Using a DLL function that requires a callback function has some additional steps. Во-первых, необходимо определить, требуется ли для функции обратный вызов. Это можно выяснить в документации по функции. First, you must determine whether the function requires a callback by looking at the documentation for the function. Далее нужно создать функцию обратного вызова в управляемом приложении. Next, you have to create the callback function in your managed application. И, наконец, вы вызываете функцию DLL, передавая указатель на функцию обратного вызова в качестве аргумента. Finally, you call the DLL function, passing a pointer to the callback function as an argument.

На рисунке ниже показана функция обратного вызова и этапы ее реализации: The following illustration summarizes the callback function and implementation steps:

Функции обратного вызова — идеальное средство для многократного выполнения некоторой задачи. Callback functions are ideal for use in situations in which a task is performed repeatedly. Другая область их применения — с функциями перечисления API Windows, такими как EnumFontFamilies, EnumPrinters и EnumWindows. Another common usage is with enumeration functions, such as EnumFontFamilies, EnumPrinters, and EnumWindows in the Windows API. Функция EnumWindows выполняет перечисление всех существующих на компьютере окон, используя функцию обратного вызова, чтобы выполнить задачу для каждого окна. The EnumWindows function enumerates through all existing windows on your computer, calling the callback function to perform a task on each window. Инструкции и примеры см. в разделе Практическое руководство. Реализация функций обратного вызова. For instructions and an example, see How to: Implement Callback Functions.

Практическое руководство. Реализация функций обратного вызова How to: Implement Callback Functions

В приведенных ниже процедуре и примере показано, как, используя вызов неуправляемого кода, можно напечатать из управляемого приложения значение дескриптора для каждого окна на локальном компьютере. The following procedure and example demonstrate how a managed application, using platform invoke, can print the handle value for each window on the local computer. В частности, для печати значения дескриптора окна в процедуре и примере используется функция EnumWindows, которая просматривает список окон, и управляемая функция обратного вызова CallBack. Specifically, the procedure and example use the EnumWindows function to step through the list of windows and a managed callback function (named CallBack) to print the value of the window handle.

Реализация функции обратного вызова To implement a callback function

Прежде чем приступить к реализации, обратите внимание на сигнатуру функции EnumWindows. Look at the signature for the EnumWindows function before going further with the implementation. Функция EnumWindows имеет следующую сигнатуру: EnumWindows has the following signature:

Признаком необходимости обратного вызова для функции является наличие аргумента lpEnumFunc. One clue that this function requires a callback is the presence of the lpEnumFunc argument. Обычно в именах аргументов, которые принимают указатель на функцию обратного вызова, присутствует префикс lp (long pointer, длинный указатель) и суффикс Func. It is common to see the lp (long pointer) prefix combined with the Func suffix in the name of arguments that take a pointer to a callback function. Документацию по функциям Win32 см. в Microsoft Platform SDK. For documentation about Win32 functions, see the Microsoft Platform SDK.

Создайте управляемую функцию обратного вызова. Create the managed callback function. В примере объявляется тип делегата CallBack , который принимает два аргумента (hwnd и lparam). The example declares a delegate type, called CallBack , which takes two arguments (hwnd and lparam). Первый аргумент — это дескриптор окна, а второй определяется приложением. The first argument is a handle to the window; the second argument is application-defined. В этом выпуске оба аргумента должны быть целыми числами. In this release, both arguments must be integers.

Функции обратного вызова обычно возвращают ненулевые значения, сообщая об успешном выполнении, и ноль, сообщая о сбое. Callback functions generally return nonzero values to indicate success and zero to indicate failure. В этом примере для продолжения перечисления в явном виде устанавливается возвращаемое значение true. This example explicitly sets the return value to true to continue the enumeration.

Создайте делегат и передайте его в качестве аргумента в функцию EnumWindows. Create a delegate and pass it as an argument to the EnumWindows function. Вызов неуправляемого кода автоматически преобразует делегат в знакомый формат обратного вызова. Platform invoke converts the delegate to a familiar callback format automatically.

Убедитесь в том, что сборщик мусора не освобождает делегат до завершения выполнения функции обратного вызова. Ensure that the garbage collector does not reclaim the delegate before the callback function completes its work. При передаче делегата в качестве параметра или поля структуры он не уничтожается в течение всего вызова. When you pass a delegate as a parameter, or pass a delegate contained as a field in a structure, it remains uncollected for the duration of the call. Таким образом, как показано в примере перечисления ниже, функция обратного вызова завершает работу, прежде чем вызов возвращает управление, не требуя никаких дополнительных действий со стороны управляемого вызывающего объекта. So, as is the case in the following enumeration example, the callback function completes its work before the call returns and requires no additional action by the managed caller.

Но если функция обратного вызова может быть вызвана после возвращения вызова, управляемый вызывающий объект должен выполнить действия, гарантирующие, что делегат не будет уничтожен, пока функция обратного вызова не завершит работу. If, however, the callback function can be invoked after the call returns, the managed caller must take steps to ensure that the delegate remains uncollected until the callback function finishes. Подробную информацию о предотвращении сборки мусора см. в разделе Маршалинг взаимодействия в подразделе, посвященном вызову неуправляемого кода. For detailed information about preventing garbage collection, see Interop Marshaling with Platform Invoke.

Лямбда-функции и реализация удобного механизма Callback-ов на C++

Постановка задачи

Необходимо реализовать удобный и быстрый механизм сохранения «указателя» на произвольную функцию и последующего его вызова с передачей аргумента (для примера возьмём тип char*).

Метод 1 – на классическом «Си»

Решая задачу «в лоб» можно получить что-то вроде такого:

Механизм очень простой и часто используемый. Но при большом количестве обратных вызовов их объявление становиться не очень удобным.

Лямбда-функции в С++

Для тех кто не слышал про С++11 (или С++0x) или пока ещё не коснулся его, расскажу про некоторые нововведения из этого стандарта. В С++11 появилось ключевое слово auto, которое может ставиться вместо типа при объявлении переменной с инициализацией. При этом тип переменной будет идентичен типу, казанному после «=». Например:

Но самое интересное это лямбда-функции. В принципе, это обычные функции, но которые могут быть объявлены прямо в выражении:

Синтаксис лямбда функции таков:

Кусок «->возвращаемый тип» может отсутствовать. Тогда подразумевается «->void». Ещё пример использования:

Данная программа выведет:

В этом примере были объявлены и проинициализированы три переменные (f1,f2 и f3) типа auto, следовательно тип которых соответствует типу стоящему справа – типу лямбда функций.
Лямбда функция, сама по себе, не является указателем на функцию (хотя в ряде случаев может бытьприведена к нему). Компилятор вызывает функцию не по адресу а по её типу – именно поэтому у каждой лямбда функции свой тип, например « ». Такой тип невозможно указать, поэтому его можно использовать только в связке с auto или шаблонами (там тип тоже может автоматически быть определён).
Стандарт так же допускает преобразование от типа лямбда к типу указателя на функцию, в случае отсутствия захватываемых переменных:

Захватываемые переменные это те переменные, которые «попадают внутрь» лямбда функции при её указании:

Эти параметры, фактически и сохраняются (копируются по значению) в переменной f.
Если указать знак & перед именем, то параметр будет передан по ссылке, а не по значению.
Адрес самой функции по-прежнему нигде не хранится.

Метод 2 – Реализация на С++

Заменив статическую функцию на лямбду можно упростить наш пример:

Вот так немножко добавив «плюсов» можно сильно упростить жизнь, главное не переборщить, чем мы сейчас и попробуем заняться. В этом примере такая конструкция будет работать, пока нам не захочется «захватить» переменные в лямбда функции. Тогда компилятор не сможет преобразовать лямбду в указатель. Вот тут, используя С++ можно сделать так:

Вот так. Чуть-чуть плюсов и код в несколько раз больше. Громоздкая реализация, а ведь здесь ещё и не учтена возможность копирования экземпляров Callback. Но удобство использования на высоте. Так же за скромной операцией «=» прячется выделение динамической памяти, да ещё конструктор – явно не вписывается в концепцию наглядности кода широко любимую верных классическому «Си» программистам.

Попробуем это исправить и максимально ускорить и упростить реализацию, не потеряв удобство.

Метод 3 – Что-то среднее

Во первых: мы убрали большой кусок связанный с виртуальными функциями и выделением памяти. Сохранение просиходит на скорости копирования нескольких байт.

Вызов тоже быстрый – от вызова двух вложенных функций (вспомогательная и сохранённая) до одной, когда компилятор встраивает одну в другую – почти идеальный вариант (от идеала отделяет один лишний аргумент «parameters»).

У такой реализации единственное ограничение – это максимальный размер захватываемых в лямбда функциях переменных. Но обычно требуется передать не так много дополнительных параметров. А при большом количестве можно и использовать динамическую память в ущерб скорости.

Читайте также:  Оболочка windows для ios
Оцените статью