Mega Code Archive

 
Categories / Delphi / Functions
 

How to Convert method pointers into function pointers

Title: How to Convert method pointers into function pointers // 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).