Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declaring external functions depending on whether they exist

I would like to declare an external function from the kernel32.dll library whose name is GetTickCount64. As far as I know, it is defined only in Vista and in later Windows versions. This means that when I define the function as follows:

function GetTickCount64: int64; external kernel32 name 'GetTickCount64';

I will certainly not be able to run my application on previous versions of Windows because of error generated on application startup.

Is there a workaround to that problem? Let's say I would like not to include that function when it does not exist and then use some substitute function in my code. How to do that? Are there any compiler directives that would help? I gues the definition would have to be surrounded by such directive and I would also have to use some directives wherever I use the GetTickCount64 founction, right?

Your help will be appreciated. Thanks in advance.

Mariusz.

like image 939
Mariusz Schimke Avatar asked Dec 22 '22 11:12

Mariusz Schimke


1 Answers

Declare a function pointer of that type, and then load the function at run time with LoadLibrary or GetModuleHandle and GetProcAddress. You can find several examples of the technique in the Delphi source code; look at TlHelp32.pas, which loads the ToolHelp library, which isn't available on older versions of Windows NT.

interface

function GetTickCount64: Int64;

implementation

uses Windows, SysUtils;

type
   // Don't forget stdcall for API functions.
  TGetTickCount64 = function: Int64; stdcall;

var
  _GetTickCount64: TGetTickCount64;

// Load the Vista function if available, and call it.
// Raise EOSError if the function isn't available.
function GetTickCount64: Int64;
var
  kernel32: HModule;
begin
  if not Assigned(_GetTickCount64) then begin
    // Kernel32 is always loaded already, so use GetModuleHandle
    // instead of LoadLibrary
    kernel32 := GetModuleHandle('kernel32');
    if kernel32 = 0 then
      RaiseLastOSError;
    @_GetTickCount := GetProcAddress(kernel32, 'GetTickCount64');
    if not Assigned(_GetTickCount64) then
      RaiseLastOSError;
  end;
  Result := _GetTickCount64;
end;
like image 87
Rob Kennedy Avatar answered Jan 01 '23 13:01

Rob Kennedy