Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 07.10.2014, 21:13
Аватар для Sergios
Sergios Sergios вне форума
Прохожий
 
Регистрация: 07.10.2014
Сообщения: 3
Версия Delphi: Delphi 7
Репутация: 10
Восклицание Callback функции

Приветствую!
Столкнулся с тем, что понадобилось использовать callback functions.
В исходниках (заголовочные файлы) функции определены как:
Код:
WINBASEAPI
BOOL
WINAPI
EnumFuncA(
    _In_ A_ENUMPROC lpEnumProc,
    _In_ DWORD                   dwFlags,
    _In_ LONG_PTR                lParam);

WINBASEAPI
BOOL
WINAPI
EnumFuncB(
    _In_ B_ENUMPROC lpEnumProc,
    _In_ DWORD            dwFlags);
Далее нашел как определены A_ENUMPROC и B_ENUMPROC:
Код:
#ifdef STRICT
typedef BOOL (CALLBACK* A_ENUMPROC)(LPSTR, LPSTR, LPSTR, DWORD, LONG_PTR);
typedef BOOL (CALLBACK* B_ENUMPROC)(LPSTR);
#else
typedef FARPROC A_ENUMPROC;
typedef FARPROC B_ENUMPROC;
#endif
Естественно возникает сразу вопрос "Как перевести на "русский" (т.е. на Delphi) вторую часть (там где определены типы (typedef)). Во-вторых, как после этого использовать callback функции. Я об этой разновидности функций имею весьма общее представление.
Гугл мне тут не помог.
Благодарю заранее за помощь.
UPD (нашел и сами функции):
Код:
BOOL CALLBACK EnumProc_A(
  _In_  LPSTR lpArg0,
  _In_  LPSTR lpArg1,
  _In_  LPSTR lpArg2,
  _In_  DWORD dwFlags,
  _In_  LONG_PTR lParam
);

BOOL CALLBACK EnumProc_B(
  _In_  LPSTR lpArg
);
Стало вообще непонятно, что кого вызывает...

Последний раз редактировалось Sergios, 07.10.2014 в 22:15.
Ответить с цитированием
  #2  
Старый 07.10.2014, 23:00
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Адрес Callback'а передается в функцию перечисления, и оттуда вызывается. Точное совпадение типов не обязательно (можно и DWORD'ами все заменить), но тогда будет неудобно использовать. Перевод:
BOOl - boolean;
CALLBACK - насколько помню, задефайнен на модификатор stdcall;
_In_ - не важен в данном случае;
LPSTR - PChar;
DWORD - DWORD;
LONG_PTR - по-моему, он Int64. Но лучше посмотреть в хедерах/MSDN.
Так что
Код:
BOOL CALLBACK EnumProc_B( _In_  LPSTR lpArg);
переведется в
Код:
function EnumProc_B(lpArg: PChar): boolean; stdcall;
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
  #3  
Старый 08.10.2014, 13:03
Аватар для Sergios
Sergios Sergios вне форума
Прохожий
 
Регистрация: 07.10.2014
Сообщения: 3
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Как ни странно, но тип BOOL в WinAPI определен как знаковое целое (int) . Поэтому не совсем корректно приравнивать его к Boolean (этот тип вообще предпочитаю не использовать). Некоторые АПИшные функции могут возвращать true как отрицательное число...
LONG_PTR для win32 определен как long, а для win64 как __int64, что соответствует типам LongInt и Int64, соответственно.
Методом научного тыка разобрался с вопросом.
Покажу на примере второй функции.
1. Определяем тип-функцию.
Код:
type
B_ENUMPROC= function (lpArg: PChar): BOOL; stdcall;

2. Описываем импортируемую функцию.
Код:
EnumFuncB(lpEnumProc: B_ENUMPROC;  dwFlags: Dword): BOOL; stdcall; external 'Oops.dll' name 'EnumFuncB';
Компилим, проверяем.
3. Определяем прототип callback-функции в строгом соответствии с п.1.
Код:
function EnumProcCallback(Arg: PChar): BOOL; stdcall;

4. определяем реализацию функции:
Код:
begin
  if Arg<>nil then 
   begin
    ; // что-то делаем с полученным аргументом
   end
  Result:=1; // True, если хотим продолжения перечисления, False (Result:=0), если не желаем продолжения
end;

5. Вызов функции перечисления.
Код:
EnumFuncB(@EnumProcCallback, (Flag1 or Flag2 or Flag3)); // пример комбинации из трех флагов, определенных в секции const.




__________________
In omnia paratus

Последний раз редактировалось Sergios, 12.10.2014 в 15:37.
Ответить с цитированием
  #4  
Старый 08.10.2014, 16:20
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

Цитата:
Вызов функции перечисления.
Код:
EnumFuncB(@EnumProcCallback, (Flag1 or Flag2 or Flag3)); // пример комбинации из трех флагов, определенных в секции const.
В данном случае символ @ писать не надо.
При его отсутствии будет делаться дополнительная проверка типа передаваемой функции.
и ещё
Лучше вместо PChar явно писать PAnsiChar.
Для старых версий Delphi не повредит, а в новых не будут появляться возможные ошибки
Ответить с цитированием
  #5  
Старый 10.10.2014, 17:41
Аватар для Sergios
Sergios Sergios вне форума
Прохожий
 
Регистрация: 07.10.2014
Сообщения: 3
Версия Delphi: Delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от icWasya
В данном случае символ @ писать не надо.
Нужно, как следует из описания типа:
Код:
typedef BOOL (CALLBACK* B_ENUMPROC)(LPSTR);
Ради интереса попробовал убрать @, ошибочка вышла
Цитата:
Сообщение от icWasya
Лучше вместо PChar явно писать PAnsiChar.
Для старых версий Delphi не повредит, а в новых не будут появляться возможные ошибки
PChar это ради примера, а так PWideChar...
__________________
In omnia paratus
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 18:13.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter