Объявление внешних функций в зависимости от того, существуют ли они - PullRequest
4 голосов
/ 25 апреля 2009

Я хотел бы объявить внешнюю функцию из библиотеки kernel32.dll, имя которой - GetTickCount64. Насколько я знаю, это определяется только в Vista и в более поздних версиях Windows. Это означает, что когда я определяю функцию следующим образом:

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

Я определенно не смогу запустить свое приложение в предыдущих версиях Windows из-за ошибки, возникшей при запуске приложения.

Есть ли решение этой проблемы? Допустим, я бы не хотел включать эту функцию, когда она не существует, а затем использовать некоторую замещающую функцию в моем коде. Как это сделать? Существуют ли какие-либо директивы компилятора, которые могли бы помочь? Я предполагаю, что определение должно быть окружено такой директивой, и мне также придется использовать некоторые директивы везде, где я использую фундамент GetTickCount64, верно?

Ваша помощь будет оценена по достоинству. Заранее спасибо.

Мариуш.

1 Ответ

11 голосов
/ 25 апреля 2009

Объявите указатель на функцию этого типа, а затем загрузите функцию во время выполнения с помощью LoadLibrary или GetModuleHandle и GetProcAddress. Вы можете найти несколько примеров этой техники в исходном коде Delphi; посмотрите на TlHelp32.pas , который загружает библиотеку ToolHelp , которая недоступна в более старых версиях 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;
...