Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Помогите разобраться с CallBack вызовами


Nil ©   (2009-03-04 18:03:00) 

я совсем запутался с процедурными типами в callback вызовах.. чтобы долго не рассказывать вот код:

DataUnit.pas:

....................
TDefragShowStatusCallback=procedure(Data: PDefragDataStruct); CDECL;
TDefragShowMoveCallback = procedure(Item: PItemStruct; Clusters, FromLcn, ToLcn,FromVcn: ULONG64 ); CDECL;
TDefragShowAnalyzeCallback = procedure(Data: PDefragDataStruct; Item:PItemStruct); CDECL;
TDefragShowDebugCallback = procedure(Level: Integer; Item: PItemStruct; Msg: PChar); CDECL;
TDefragDrawClusterCallback= procedure(Data: PDefragDataStruct; ClusterStart, ClusterEnd: ULONG64; Color: Integer); CDECL;
TDefragClearScreenCallback= procedure(Format: PChar); CDECL;
.....................


unit uAnalyzeThread;

interface

uses
 Classes, Windows, Graphics, DataUnit;

type
 TAnalyzeThread = class(TThread)
 private
   { Private declarations }
   procedure Upd_VLC_ShowAnalyzeCallback;
   procedure ShowAnalyzeCallback(Data: PDefragDataStruct; Item:PItemStruct); CDECL;
 protected
   procedure Execute; override;
 end;

procedure RunJkDefrag(
 Path: PWideChar;
 Mode: Integer;
 Speed: Integer;
 FreeSpace: Double;
 Excludes: PWideChar;
 SpaceHogs: PWideChar;
 Running: PInteger;
 RedrawScreen: PInteger;
 ShowStatus: TDefragShowStatusCallback;
 ShowMove: TDefragShowMoveCallback;
 ShowAnalyze: TDefragShowAnalyzeCallback;
 ShowDebug: TDefragShowDebugCallback;
 DrawCluster: TDefragDrawClusterCallback;
 ClearScreen: TDefragClearScreenCallback;
 DebugMsg: PWideChar);
 CDECL;external 'JkDefragLib.dll' name 'RunJkDefrag';

procedure StopJkDefrag(Running: Pointer; TimeOut: Integer);
 CDECL;external 'JkDefragLib.dll' name 'StopJkDefrag';

var
   spacehogs:pwidechar=nil;
   Excludes:pwidechar=nil;
   DebugMessages:pwidechar=nil;
   running,redrawscreen:integer;
   count:integer=0;
   ThrItem:PItemStruct;
   ThrData: PDefragDataStruct;

implementation

uses Unit1, SysUtils;

procedure TAnalyzeThread.Upd_VLC_ShowAnalyzeCallback;
begin
 if(ThrItem<>nil) then form1.label1.caption:= ThrItem^.Path;
 form1.label3.caption:= inttostr(ThrData^.CountFragmentedItems);
end;

procedure TAnalyzeThread.ShowAnalyzeCallback(Data: PDefragDataStruct; Item:PItemStruct); CDECL;
begin
 ThrItem:=Item;
 ThrData:=Data;
 Synchronize(Upd_VLC_ShowAnalyzeCallback);
end;

procedure TAnalyzeThread.Execute;
var
 PShowAnalyzeCallback: TDefragShowAnalyzeCallback;
begin
//  PShowAnalyzeCallback:=ShowAnalyzeCallback;

 running:=0;
 redrawscreen:=0;
 DebugMessages:=nil;
 Excludes:=nil;
 spacehogs:=nil;
 RunJkDefrag('C:', 0, 100, 10, excludes, spacehogs, @running, nil, nil, nil, ShowAnalyzeCallback, nil, nil, nil, nil);
end;

end.


в RunJkDefrag ругается на ShowAnalyzeCallback ошибкой:
[DCC Error] uAnalyzeThread.pas(76): E2009 Incompatible types: 'regular procedure and method pointer'

подскажите пож, что не так делаю...


Nil   (2009-03-09 15:38:00) [1]

спасибо большое, выручили!


clickmaker   (2009-03-05 14:10:00) [2]

type
TAnalyzeData = record
  ThrItem:PItemStruct;
  ThrData: PDefragDataStruct;
end;
PAnalyzeData = ^TAnalyzeData;

procedure ShowAnalyzeCallback(Data: PDefragDataStruct; Item:PItemStruct); CDECL;
var
 Data: TAnalyzeData;
begin
 Data.ThrItem:=Item;
 Data.ThrData:=Data;
 SendMessage(form1.Handle, WM_ShowAnalyze, 0, Integer(@Data));
end;

procedure TForm1.WMShowAnalyze(var Msg: TMessage);
var
 Data: PAnalyzeData;
begin
 Data := PAnalyzeData(Msg.LParam);
 if(Data.ThrItem<>nil) then label1.caption:= ThrItem^.Path;
 label3.caption:= inttostr(Data.ThrData^.CountFragmentedItems);
end;


Ega23   (2009-03-05 12:19:00) [3]

Не используй Synchronize, делай SendMessage, а в форме (или где там) его обрабатывай.


Nil   (2009-03-05 12:13:00) [4]


> если ThrItem и ThrData не свойства класса, то нафиг там
> метод класса?

было бы конечно красивее сделать эти переменные свойством класса, но чтобы было наверняка, вынес их из класса чтобы ещё каких нибудь камней не повылазило..


Nil   (2009-03-05 12:11:00) [5]


>
> Откуда такое желание? Там, где ожидается процедура, должна
> быть именно процедура, потому что ссылка на метод требует
> ещё и ссылки на объект, а заставить вызывающую сторону хранить
> эту ссылку нет, если это чужой код.
>
> Можно хакерскими методами подсунуть метод там, где нужна
> процедура, но, чтобы это устойчиво работало, на метод накладываются
> жёсткие ограничения: нельзя обращаться к полям объекта (не
> только прямо, но и опосредовано - через свойства, вызовы
> других методов и т.п.), нельзя вызывать из него виртуальные
> и динамические методы, и вообще нельзя ничего, что не будет
> работать без Self. Оно вам надо? С такими ограничениями
> логичнее делать процедуру.


усвоил, чем проще тем лучше)
возник попутный вопрос, если вынесу ShowAnalyzeCallback из класса в regular как тогда я смогу обратится к методу Synchronize() класса TThread?

в ShowAnalyzeCallback сейчас есть строчка Synchronize(Upd_VLC_ShowAnalyzeCallback) а если ShowAnalyzeCallback вынесу из класса как тогда выполнить Synchronize(Upd_VLC_ShowAnalyzeCallback)? нельзя же написать Synchronize(TAnalyzeThread.Upd_VLC_ShowAnalyzeCallback)?


clickmaker   (2009-03-04 18:49:00) [6]

если ThrItem и ThrData не свойства класса, то нафиг там метод класса?


Григорьев Антон   (2009-03-04 18:34:00) [7]


> как regular procedure привести или представить в method
> pointer


Откуда такое желание? Там, где ожидается процедура, должна быть именно процедура, потому что ссылка на метод требует ещё и ссылки на объект, а заставить вызывающую сторону хранить эту ссылку нет, если это чужой код.

Можно хакерскими методами подсунуть метод там, где нужна процедура, но, чтобы это устойчиво работало, на метод накладываются жёсткие ограничения: нельзя обращаться к полям объекта (не только прямо, но и опосредовано - через свойства, вызовы других методов и т.п.), нельзя вызывать из него виртуальные и динамические методы, и вообще нельзя ничего, что не будет работать без Self. Оно вам надо? С такими ограничениями логичнее делать процедуру.


Медвежонок Пятачок   (2009-03-04 18:30:00) [8]

метод он у класса.
а регулар он сам по себе


Nil   (2009-03-04 18:29:00) [9]

сорь, но читать я научился, а как regular procedure привести или представить в method pointer пока не нет, зачем и задал вопрос...


Anatoly Podgoretsky   (2009-03-04 18:14:00) [10]

Вот жто

> Incompatible types: 'regular procedure and method pointer'


Наверх

Титульная страница Поиск, карта сайта Написать письмо