Перед тем как программа начнет выполнение, она загружается в оперативную память. Конечно же, код загружается не полностью, а только та его часть, которая нужна для инициализации и работы программы, но иногда ее размер может быть значительным. В одной из фирм, где я совсем недолго работал, корпоративная программа занимала 50 Мбайт в исполняемом файле. Конечно же, загрузка происходила не очень быстро, но терпимо, только потому, что инициализация осуществлялась оптимальным образом для такого большого проекта.

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

Очень часто для уменьшения размера программы код размещают в динамических библиотеках. В этом случае вы действительно можете увеличить скорость загрузки, но не всегда.

Наиболее эффективным решением является перенос в библиотеку такого кода, который будет выполняться редко. Например, окно О программе пользователь может вообще никогда не посмотреть, а его в основном делают красивым, с изображениями и интересными эффектами. Так зачем же все это хранить в основном файле? Конечно же, смысла нет, поэтому такие вещи очень часто выносят в отдельные библиотеки.

Простой перенос кода в динамическую библиотеку не дает выигрыша в скорости, если не загружать ее динамически. Самый простой способ подключить dll-файл в Delphi - это добавить в начало модуля описание функции, например, такое:

function FuncName(Paraml: Type): Boolean: stdcall;
external 'filename.dll' index 1:

Здесь объявляется функция с именем FuncName, которая расположена в файле filename.dll. После этого функцию можно использовать, как будто она описана в основном проекте и не вынесена в отдельный файл При таком объявлении Delphi откомпилирует код так, что библиотека будет загружаться во время запуска программы, а это сведет преимущество dll-файлов на нет.

Чтобы действительно повысить скорость загрузки, необходимо подключать библиотеку динамически. Это позволит производить загрузку только в тот момент, когда это необходимо.

Допустим, что в динамически подключаемой библиотеке имеется функция следующего вида:

function CalculateSomthing(Sum: Integer): Integer;
export; stdcall:

Теперь, чтобы ее использовать динамически, нельзя явно указывать функцию и ее местоположение. Мы должны объявить в разделе type новый тип, который будет иметь тип функции. Это необходимо для того, чтобы программа знала параметры и тип возвращаемого значения функции, которая будет загружаться:

CalcFunc = function (Summ: Integer): Integer;
stdcall:

Теперь функция будет динамической (листинг 2.1). Для этого явно загружаем ее функцией LoadLibrary. В качестве параметра нужно указать библиотеку или полный/относительный путь к ней (если она расположена в папке, которая недоступна программе). Если загрузка пройдет успешно, то функция возвратит ненулевое значение, иначе результат будет равен 0. Результат работы функции LoadLibrary - это указатель на загружаемую библиотеку, поэтому его надо сохранить для дальнейшей работы.

Листинг 2.1. Динамическая загрузка библиотеки

procedure TForml.ButtonlClick(Sender: TObject): var
dl 1 Handle: THandle: fCalc: CalcFunc;
iResult: Integer;
begin
dllHandle := LoadLibraryCtest.dll'):

if dllHandle = 0 then exit: // Библиотека не загрузилась

@fCalc := GetProcAddress(dllHandle. 'CalculateSomthing');

if @fCalc=nil then exit; // Функция не найдена

iResult = fCalc(lOO): FreeLibrary(dllHandle);
end;

На следующем этапе ищем необходимую функцию внутри загруженной библиотеки. Для этого используется функция GetProcAddress. В качестве первого параметра используется указатель на загруженную библиотеку, а второго - имя искомой функции. Результатом будет указатель на найденную функцию, который сохраняем в переменной, имеющей тип библиотечной функции. Если результат равен нулю, то функция не найдена. Такая ситуация может возникнуть из-за того? что библиотека была изменена или мы загрузили другой dll-файл с таким же именем.

Если все прошло успешно, то вызываем функцию через переменную.

По окончании работы с библиотечными функциями обязательно выгружаем библиотеку из памяти. Это осуществляется при помощи функции РгееИЬгагу, где в качестве указателя передается указатель на загруженную библиотеку.

Таким образом, сШ-файл будет загружаться не автоматически при старте программы, а только тогда, когда это нужно. Так можно повысить скорость запуска основного файла.

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

Помните, что сШ-файлы нужны не только для увеличения скорости загрузки запускных файлов, но и для разделения одних и тех же функций между несколькими приложениями

2.2. Знания о системе || Оглавление || 2.4. Инициализация


Delphi в шутку и всерьез: что умеют хакеры



Новости за месяц

  • Декабрь
    2021
  • Пн
  • Вт
  • Ср
  • Чт
  • Пт
  • Сб
  • Вс
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31