Текущий архив: 2006.12.31;
Скачать: CL | DM;
Внизправильная реализация MethodToProcedure Найти похожие ветки
← →
MetalFan © (2006-10-26 13:28) [0]решил вынести в отдельную тему.
проблема: приведение метода класса к процедурному типу (простите, если термины неверны) для передачи в кач. callback функции WinApi или в классы. (типа TList.Sort()).
найдена следующая реализация в madCollection (http://www.madshi.net/)
описание из help"a:
Sometimes you need to give a procedure address in to a Windows API, but you would rather give in a method instead. In such a situation the function "MethodToProcedure" can come in handy. You give in a method address and your current "Self" value and you get a procedure address as the result, which you then can give in to a Windows API.
Please note that this works only for *stdcall* methods! Don"t use it for any other calling convention! (But since almost all Windows APIs are stdcall, this should not be a big problem.)
After you don"t need the procedure pointer anymore, please free it with "VirtualFree".function MethodToProcedure (self : TObject;
methodAddr : pointer) : pointer; overload;
function MethodToProcedure (method : TMethod) : pointer; overload;
Here comes a little example which demonstrates a correct and useful usage of "MethodToProcedure":
unit EnumWindows;
// this unit implements a little class named TEnumWindows, which does nothing
// but enumerate all windows
interface
implementation
uses Windows, SysUtils, madTools;
type
TEnumWindows = class
private
function EnumCallbackMethod(window: dword; lParam: integer) : bool; stdcall;
public
constructor Create;
end;
constructor TEnumWindows.Create;
var EnumCallbackProc : pointer;
begin
inherited;
// you must give in a procedure address into EnumWindows
// if you would give in "@TWindowList.EnumCallbackMethod" your code would crash
// because methods have an additional hidden "Self" parameter
// so we need to convert our method to a procedure first
EnumCallbackProc := MethodToProcedure(Self, @TEnumWindows.EnumCallbackMethod);
// "EnumCallbackProc" now contains a pointer to a newly allocated procedure
// which does nothing but jump to our "EnumCallbackMethod" with the correct parameters
EnumWindows(EnumCallbackProc, 0);
// don"t forget to free the allocated procedure
VirtualFree(EnumCallbackProc, 0, MEM_RELEASE);
end;
function TEnumWindows.EnumCallbackMethod(window: dword; lParam: integer) : bool; stdcall;
begin
result := true;
// do anything with the "window"s you get here...
[...]
end;
end.function MethodToProcedure(self: TObject; methodAddr: pointer) : pointer;
type
TMethodToProc = packed record
popEax : byte; // $58 pop EAX
pushSelf : record // push self
opcode : byte; // $B8
self : pointer; // self
end;
pushEax : byte; // $50 push EAX
jump : record // jmp [target]
opcode : byte; // $FF
modRm : byte; // $25
pTarget : ^pointer; // @target
target : pointer; // @MethodAddr
end;
end;
var mtp : ^TMethodToProc absolute result;
begin
mtp := VirtualAlloc(nil, sizeOf(mtp^), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
with mtp^ do begin
popEax := $58;
pushSelf.opcode := $68;
pushSelf.self := self;
pushEax := $50;
jump.opcode := $FF;
jump.modRm := $25;
jump.pTarget := @jump.target;
jump.target := methodAddr;
end;
end;
Мастера, объясните ошибочность такого подхода, а так же, если не сложно, покажите пример кода, выполняющий эту задачу
← →
Юрий Зотов © (2006-10-26 13:42) [1]> объясните ошибочность такого подхода
Его главная ошибочность в том, что он на фиг не нужен. Можно, конечно, чесать правое ухо и левой ногой, но гораздо проще и гораздо удобнее делать это правой рукой.
> покажите пример кода
Пишется обычный callback, а в вызывающую его функцию передается ссылка на объект. При вызове callback"а эта ссылка передается ему - а уж он знает, что с ней делать. Например, можно просто вызвать метод этого объекта - и получится как раз то, что хотелось. Но... правой рукой, а не левой ногой.
← →
Сергей М. © (2006-10-26 13:55) [2]
> MetalFan © (26.10.06 13:28)
Сравни с Make/FreeObjectInstance() (classes.pas), удивись ..)
← →
Ketmar © (2006-10-26 14:11) [3]>[1] Юрий Зотов(c) 26-Oct-2006, 13:42
>Его главная ошибочность в том, что он на фиг не нужен.
madshi не зря назвал это "madCollection". %-)
← →
MetalFan © (2006-10-26 14:37) [4]Юрий Зотов © (26.10.06 13:42) [1]
можно и так) но всетаки хочется поизвращенней)
Сергей М. © (26.10.06 13:55) [2]
сравнил... похоже...
а можете помочь приведенный код до ума довести? мне опыта не хватает(
← →
Ketmar © (2006-10-26 14:49) [5]>[4] MetalFan(c) 26-Oct-2006, 14:37
>а можете помочь приведенный код до ума довести?
какой? который от madshi? так он отлично работает.
← →
MetalFan © (2006-10-26 14:55) [6]а можно его не для WinApi использовать?
← →
Ketmar © (2006-10-26 15:02) [7]>[6] MetalFan(c) 26-Oct-2006, 14:55
>а можно его не для WinApi использовать?
не надо.
← →
Rule © (2006-10-26 15:16) [8]MetalFan © (26.10.06 14:55) [6]
зачем ????
← →
MetalFan © (2006-10-26 15:42) [9]хорошо, а как его(код) модифицировать, чтобы можно было использовать и для WinApi и для callback в классах делфи?
← →
Ketmar © (2006-10-26 15:43) [10]>[9] MetalFan(c) 26-Oct-2006, 15:42
>хорошо, а как его(код) модифицировать, чтобы можно было
>использовать и для WinApi и для callback в классах делфи?
ЗАЧЕМ???
← →
MetalFan © (2006-10-26 15:47) [11]Ketmar © (26.10.06 15:43) [10]
а почему нет?
чтобы например у наследников TList вызывать Sort с методом тогоже класса...
← →
Ketmar © (2006-10-26 15:54) [12]>[11] MetalFan(c) 26-Oct-2006, 15:47
у "наследников TList" никто не мешает сделать дополнительный метод.
← →
MetalFan © (2006-10-26 15:59) [13]>Ketmar © (26.10.06 15:54) [12]
т.е. скопировать тот же код, немного его изменив?
а зачем, если можно поизвращаться...
вон, Rule говорит, что заработало у него %)
← →
Ketmar © (2006-10-26 16:01) [14]>[13] MetalFan(c) 26-Oct-2006, 15:59
>а зачем, если можно поизвращаться...
ну как тебе сказать, чтобы без мата? %-)
← →
MetalFan © (2006-11-13 08:43) [15]
> Ketmar © (26.10.06 16:01) [14]
>
> >[13] MetalFan(c) 26-Oct-2006, 15:59
> >а зачем, если можно поизвращаться...
> ну как тебе сказать, чтобы без мата? %-)
>
ну уж как нибудь нельзя чтоль?!
только за метлой не посылай ;)
Страницы: 1 вся ветка
Текущий архив: 2006.12.31;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.041 c