Delphi World - Как преобразовать указатель на метод в указатель на функцию
Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Как преобразовать указатель на метод в указатель на функцию

Автор: http://www.swissdelphicenter.ch

// Converting method pointers into function pointers

// Often you need a function pointer for a callback function.
// But what, if you want to specify a method as
// an callback? Converting a method pointer to a function
// pointer is not a trivial task; both types are
// incomatible with each other. Although you have the
// possibility to convert like this "@TClass.SomeMethod",
// this is more a hack than a solution, because it restricts
// the use of this method to some kind of a class
// function, where you cannot access instance variables.
// If you fail to do so, you'll get a wonderful gpf.
// But there is a better solution: run time code generation!
// Just allocate an executeable memory block, and
// write 4 machine code instructions into it: 2 instructions
// loads the two pointers of the method pointer
// (code & data) into the registers, one calls the method
// via the code pointer, and the last is just a return
// Now you can use this pointer to the allocated memory
// as a plain funtion pointer, but in fact you are
// calling a method for a specific instance of a Class.

type
  TMyMethod = procedure of object;

function MakeProcInstance(M: TMethod): Pointer;
begin
  // allocate memory
  GetMem(Result, 15);
  asm
    // MOV ECX,
    MOV BYTE PTR [EAX], $B9
    MOV ECX, M.Data
    MOV DWORD PTR [EAX+$1], ECX
    // POP EDX
    MOV BYTE PTR [EAX+$5], $5A
    // PUSH ECX
    MOV BYTE PTR [EAX+$6], $51
    // PUSH EDX
    MOV BYTE PTR [EAX+$7], $52
    // MOV ECX,
    MOV BYTE PTR [EAX+$8], $B9
    MOV ECX, M.Code
    MOV DWORD PTR [EAX+$9], ECX
    // JMP ECX
    MOV BYTE PTR [EAX+$D], $FF
    MOV BYTE PTR [EAX+$E], $E1
  end;
end;

procedure FreeProcInstance(ProcInstance: Pointer);
begin
  // free memory
  FreeMem(ProcInstance, 15);
end;

// After all, you should not forget to release the allocated memory. 
// "TMyMethod" can be modified according your specific needs, e.g. 
add some parameters for a WindowProc. 
// N.B.: Yes, I know, Delphi has those "MakeProcInstance" 
function in its forms unit. 
// But this works a little bit different, has much more overhead, 
// and most important, you have to use the forms unit, which increases 
the size of your exe drastically, 
// if all other code doesn't use the VCL 
(e.g. in a fullscreen DirectX/OpenGl app). 
Проект Delphi World © Выпуск 2002 - 2017
Автор проекта: Эксклюзивные курсы программирования