The MustangPeak Common Library (http://code.google.com/p/mustangpeakcommonlib/) contains the following code that converts a method to a procedure that can be used in a callback:
const
AsmPopEDX = $5A;
AsmMovEAX = $B8;
AsmPushEAX = $50;
AsmPushEDX = $52;
AsmJmpShort = $E9;
type
TStub = packed record
PopEDX: Byte;
MovEAX: Byte;
SelfPointer: Pointer;
PushEAX: Byte;
PushEDX: Byte;
JmpShort: Byte;
Displacement: Integer;
end;
{ ----------------------------------------------------------------------------- }
function CreateStub(ObjectPtr: Pointer; MethodPtr: Pointer): Pointer;
var
Stub: ^TStub;
begin
// Allocate memory for the stub
// 1/10/04 Support for 64 bit, executable code must be in virtual space
Stub := VirtualAlloc(nil, SizeOf(TStub), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
// Pop the return address off the stack
Stub^.PopEDX := AsmPopEDX;
// Push the object pointer on the stack
Stub^.MovEAX := AsmMovEAX;
Stub^.SelfPointer := ObjectPtr;
Stub^.PushEAX := AsmPushEAX;
// Push the return address back on the stack
Stub^.PushEDX := AsmPushEDX;
// Jump to the 'real' procedure, the method.
Stub^.JmpShort := AsmJmpShort;
Stub^.Displacement := (Integer(MethodPtr) - Integer(@(Stub^.JmpShort))) -
(SizeOf(Stub^.JmpShort) + SizeOf(Stub^.Displacement));
// Return a pointer to the stub
Result := Stub;
end;
{ ----------------------------------------------------------------------------- }
{ ----------------------------------------------------------------------------- }
procedure DisposeStub(Stub: Pointer);
begin
// 1/10/04 Support for 64 bit, executable code must be in virtual space
VirtualFree(Stub, SizeOf(TStub),MEM_DECOMMIT);
end;
I would appreciate any help in converting it to 64bit. I know that the calling convention in Win64 is different and that up to four parameters are passed into registers. So CreateStub may have to be modified to include the number of parameters. It is actually not used with more than four parameters which are integers or pointers (no floating point arguments).
Here is the 64-bit version of CreateStub. Kudos to Andrey Gruzdev who provided the code.