User:ConradPino/Christian Wimmer/Dynamic Function Invocation Update
Contents
Problem Statement
We need a replacement for the dynamic loading functions for all WinAPI functions. At the moment a function is dynamically loaded in this way:
var _GetWindowModuleFileNameW: Pointer; function GetWindowModuleFileNameW; begin GetProcedureAddress(_GetWindowModuleFileNameW, user32, 'GetWindowModuleFileNameW'); asm MOV ESP, EBP POP EBP JMP [_GetWindowModuleFileNameW] end; end;
However, if Delphi gets 64bit support this won't work anymore because in 64bit function parameters are stored in registers (and unused registers are cleared when a function is called) So we need a replacement and Delphi 2009 introduced the reserverd word "delayed" which is added behind the function declaration. (Furthermore stdcall; is deprecated) I had this solution in mind:
- "Remove" the asm function and add "delayed" to the function declaration if "DYNAMIC_LINK" compiler switch is active. Usually the functions are declared twice. One is defined in the interface part and another one in the implementation part. The static loaded function looks like this:
function DefRawInputProc; external user32 name 'DefRawInputProc';
- So I think adding "delayed;" here (in case of DYNAMIC_LINK" compiler switch is active) should be fine.
function DefRawInputProc; external user32 name 'DefRawInputProc' {$IFDEF DYNAMIC_LINK}delayed{$ENDIF DYNAMIC_LINK};
- Of course it means that the whole DYNAMIC_LINK compiler stuff must be rethinked because "delayed" should only be used in D2009 and newer.
- Old implementation still should use the asm function (thus I put "Remove" into quotes). Maybe we add DELAYED_LINK directive (or different name) that undefines DYNAMIC_LINK (so the static part is used) but activates the reserverd word "delayed" in the function declaration.
- Unfortunately it is a lot of work and I don't even know whether it will work. Maybe a program could do it automatically? Furthermore D2009 is necessary.
Design Offer
JediAPILib.inc
This implementation leaves all options open to the developer and remains down level compatible:
{$IFDEF DELPHI2010_UP} {$IFDEF DELAYED_LINKING} {$UNDEF DYNAMIC_LINK} {$ENDIF DELAYED_LINKING} {$ELSE} {$IFDEF DELAYED_LINKING} {$UNDEF DELAYED_LINKING} {$DEFINE DYNAMIC_LINK} {$ENDIF DELAYED_LINKING} {$ENDIF}
DELPHI2010_UP | DELAYED_LINKING | DYNAMIC_LINK | Link Method |
---|---|---|---|
False | False | False | Static |
False | False | True | Dynamic |
False | True, Undefined | False, Defined | Dynamic |
False | True, Undefined | True, Defined | Dynamic |
True | False | False | Static |
True | False | True | Dynamic |
True | True | False, Undefined | Delayed |
True | True | True, Undefined | Delayed |
Any Jwa unit
{$IFDEF DYNAMIC_LINK} .. same asm stuff here unchanged {$ELSE} function DefRawInputProc; external user32 name 'DefRawInputProc' {$IFDEF DELAYED_LINKING}delayed{$ENDIF DELAYED_LINKING}; {$ENDIF DYNAMIC_LINK}
Some things to think about
- delayed must be placed behind the name or index of the declaration. There must be no semicolon between them. Any other position results into an error. A parser must take it into account.
- DYNAMIC_LINK may be used in other situations like in real code. ChristianWimmer 21:58, 31 January 2010 (UTC) : I can't recall any such situation but we should be sure.
- To [1] the error handling of functions that could not be loaded dynamically is changed. JWA uses JwaWinType.pas::GetProcedureAddress which raises EJwaLoadLibraryError or EJwaGetProcAddressError.
- We could leave it this way and Delphi raises an EExternalException [2]
- We could add a delayed load handler like shown in [3] and throw the JWA exceptions. However this will also cover all the custom made delayed loading functions.
References
- [1] http://blog.delphi-jedi.net/2009/08/29/version-checking-for-delphi/
- [2] http://blogs.embarcadero.com/abauer/2009/08/25/38894
- [3] http://blogs.embarcadero.com/abauer/2009/08/29/38896
Use Cases
Now that Microsoft has merged the Platform SDK and .NET Framework SDK to form the Windows SDK, dealing with managed code is unavoidable.
Unmanaged (Native) Code
Native 32-bit Code
JWAPI and JWSCL support 32-bit native code.
Native 64-bit Code
Is JEDI-APILIB currently known to support Native 64-bit Code?
ChristianWimmer 21:18, 31 January 2010 (UTC):
- Not supported, neither JWA nor JWSCL (depends heavily on JWA) will work on x64.
- It may work if the compiler def DYNAMIC_LINK is unset but there are many type definitions that must be changed (e.g. DWORD_PTR). All dynamic loading functions must be changed to accommodate the new 64bit architecture.
Conrad T. Pino 00:08, 1 February 2010 (UTC):
- Until a 64-bit native code compiler standard appears this seems pointless. The Object Pascal choices are not large.
- Free Pascal supports 64-bit but should their implementation differ from some future Delphi release the rework could be painful.
- Until a compelling reason appears I shall ignore Native 64-bit Code.
ChristianWimmer 18:39, 1 February 2010 (UTC):
- Since Freepascal (FP) does not support the reserved word delayed we cannot test my first apporach. However, we can test different approaches with FP. There is still some research to do.
Managed (.NET) Code
An Overview of Managed/Unmanaged Code Interoperability
ChristianWimmer 21:18, 31 January 2010 (UTC):
- Not supported. Delphi does not support .NET. but Prism does!
Conrad T. Pino 00:10, 1 February 2010 (UTC):
- Since Chistian's made no case to support Managed Code, I shall ignore it.
Delphi Versions
- With which version does Delphi support Managed Code?
ChristianWimmer 21:18, 31 January 2010 (UTC) : Delphi Prism (one separate product).
- With which version does Delphi Native 64-bit Code?
ChristianWimmer 21:18, 31 January 2010 (UTC) : Unknown, up to Embarcadero. See their roadmap(s).