Объявление внешних функций в зависимости от того, существуют ли они
-
16-09-2019 - |
Вопрос
Я хотел бы объявить внешнюю функцию из библиотеки kernel32.dll с именем GetTickCount64.Насколько я знаю, он определяется только в Vista и более поздних версиях Windows.Это означает, что когда я определяю функцию следующим образом:
function GetTickCount64: int64; external kernel32 name 'GetTickCount64';
Я определенно не смогу запустить свое приложение в предыдущих версиях Windows из-за ошибки, возникающей при запуске приложения.
Есть ли обходной путь этой проблемы?Допустим, я хотел бы не включать эту функцию, если она не существует, а затем использовать в своем коде какую-нибудь замещающую функцию.Как это сделать?Есть ли какие-нибудь директивы компилятора, которые могли бы помочь?Я предполагаю, что определение должно быть окружено такой директивой, и мне также придется использовать некоторые директивы везде, где я использую функцию GetTickCount64, верно?
Ваша помощь будет оценена по достоинству.Заранее спасибо.
Мариуш.
Решение
Объявите указатель на функцию этого типа, а затем загрузите функцию во время выполнения с помощью 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;