tema_dll

advertisement
Тема ?. Использование библиотек DLL.
Файл 446966401
С. 1 из 9
Тема ?. Использование динамически подключаемых библиотек (DLL, Dynamic Link
Library)
1. Общие положения
1.1. Суть библиотек DLL
1.2. Создание и использование библиотек DLL в среде Delphi
1.3. DLL и разработка интерфейса
2. Пример использования DLL
2.1. Разработка процедуры, заносимой в библиотеку
2.2. Структура и содержание библиотеки
2.3. Использование библиотеки в консольном варианте приложения
2.4. Использование библиотеки в варианте с графическим интерфейсом
1. Общие положения
1.1. Суть библиотек DLL
Динамически подключаемые библиотеки, или DLL – средство автономного хранения программного
кода (как правило, процедур) и ресурсов (например, форм). Это самый простой способ реализации автономности компонентов приложения (за счет вынесения их в библиотеку) и предоставления в общее пользование готовых компонентов.
Это общие преимущества, предоставляемые любыми программными библиотеками. Их следствиями являются:
- улучшение структуры и наглядности приложения за счет уменьшения длины кода (замены
фрагмента кода вызовом библиотечной процедуры);
- улучшение модифицируемости приложения за счет возможности модификации кода, вынесенного в библиотеку, без изменения основной части приложения;
- накопление результатов труда программистов.
Библиотеки DLL оформляются как файлы с расширением .dll. В среде Delphi библиотеки по структуре схожи с библиотеками подпрограмм в языках программирования типа Фортран, C и C++. Размещаются библиотеки с расчетом на удобство использования: либо в текущем каталоге приложения (там, где расположен .exe-файл приложения), либо в системных каталогах Windows (стандартно – в Windows\System32). Если одна и та же библиотека используется несколькими приложениями, то она копируется в текущий каталог каждого из приложений.
Библиотека подключается к приложению динамически, т.е. после его запуска, а не при компиляции. Основной вариант поиска библиотеки – сначала в текущем каталоге, затем в каталоге Windows\System32. В зависимости от настройки ОС при отсутствии библиотеки в указанных каталогах
приложение может просто не работать, может производиться поиск в других каталогах либо выдаваться запрос на выбор библиотеки.
Мы рассмотрим вариант включения в библиотеку только процедур и функций.
1.2. Создание и использование библиотек DLL в среде Delphi
 Создание библиотеки DLL
•• Выполнить команду File/New/Other/DLL Wizard. Создается пустая заготовка файла проекта
библиотеки. Модуль библиотеки инициируется ключевым словом library со стандартным именем:
library Project2;
uses
SysUtils,
Classes;
{$R *.res}
begin
Тема ?. Использование библиотек DLL.
Файл 446966401
С. 2 из 9
end.
•• Файлы и модули библиотек именуются по тем же правилам, что и модули Unit: имя модуля
должно совпадать с именем файла, где этот модуль сохраняется. Это надо учитывать при переименовании библиотеки, т.е. сохранении ее под желаемым именем.
•• В раздел описаний вставить описания констант и типов, глобальных для процедур библиотеки.
В раздел процедур вставить описания процедур. Добавить раздел экспортируемых процедур:
exports
<список имен процедур>;
Получится следующее:
library <имя библиотеки>;
uses
SysUtils,
Classes;
{$R *.res}
< описания констант и типов, глобальных для процедур >
< описания процедур >
// раздел экспортируемых процедур
exports
<список имен процедур>;
begin
end.
•• Сохранить проект библиотеки
•• Скомпилировать проект библиотеки. Результат – файл <имя библиотеки>.dll
•• Для изменения библиотеки (коррекции, добавления процедур) следует открыть проект, внести
изменения, скомпилировать проект.
 Подключение библиотеки DLL
•• В программе, использующей библиотеку, в разделе описаний должны содержаться описания
констант и типов, глобальных для процедур – такие же, как в библиотеке.
•• В разделе описания процедур программы каждая из процедур библиотеки описывается как импортируемая, или внешняя:
<заголовок процедуры>;
external ‘<имя библиотеки>.dll’
1.3. DLL и разработка интерфейса
Здесь представляет интерес ситуация, когда некоторое приложение едино с точки зрения выполняемых функций, но должно иметь различные интерфейсы в различных использованиях (например, для разных классов пользователей). В таком случае должна быть обеспечена относительная
автономность разработки компонентов, реализующих интерфейс, и интерфейсно-независимых
компонентов, выполняющих обработку данных – «движок». Последний может быть занесен в библиотеку, и тогда по сути различные приложения могут использовать единую общую часть.
Такое разделение просто только на первый взгляд; это довольно нетривиальная задача уже в
обычном программировании. Если же разные интерфейсы создаются с помощью инструментов
разного уровня (например, средствами языка программирования и интегрированными визуальными средствами разработки приложений), то картина становится с ног на голову: различия в реализации в большой степени должны учитываться на уровне проекта. Методы здесь могут быть только эвристическими, а общие принципы остаются теми же, что при проектировании ПО в целом.
Возможно, что «одно и то же приложение с разными интерфейсами» для одних задач окажется
рациональнее выполнить программно как несколько независимых приложений, для других – с выделением разных интерфейсных и общей обрабатывающей части.
Тема ?. Использование библиотек DLL.
Файл 446966401
С. 3 из 9
2. Пример использования DLL
Полностью два варианта приложения, использующих библиотеку, размещены в прилагаемых каталогах primer_tema3vopr2dll и InterfForTopDown (архивы .rar). Цель приводимого ниже текста –
пояснение основных моментов, касающиеся разработки библиотеки.
2.1. Разработка процедуры, заносимой в библиотеку
В рамках задания по лабораторной работе № 4 для задачи top_down оформим обработку данных
(т.е. собственно решение задачи) в виде процедуры и запишем в библиотеку DLL.
Будем базироваться на имеющейся разработке (см. курс «Технология разработки ПО», тема 3,
вопрос 2). Здесь на уровне 0 проектирования алгоритма обработка совмещена с выводом результатов и представлена абстракцией А0.3:
.......................
{решение задачи} {вх.: n, b, m, a; вых.: a или maxmin}
А0.3. <решение задачи с выводом результатов по обр 3>
.......................
Чтобы процедура решения была пригодна для использования во всех вариантах приложения (т.е.
вариантах с разными интерфейсами), из нее следует убрать ввод-вывод.
Задача имеет три варианта решения, или три вида результатов, каждому из которых соответствует
своя форма (см. уровень 1, задача А0.3):
Обр 3.1
Результаты
Обр 3.2.1
Измененная матрица:
Обр 3.2.2
(совпадает
с обр 2.4)
Обр 3.2.3
Обр 3.2.4
<a(1,1)> <a(1,2)> . . . <a(1,n)>
........
1-й
вариант
решения
<a(m,1)> <a(m,2)> . . . <a(m,n)>
В массиве b есть одинаковые элементы, но матрица не содержит
строки со всеми положительными элементами и не меняется
Максимальное значение минимумов строк матрицы = < maxmin >
2-й вариант
3-й вариант
Разделить обработку и вывод можно так: помимо входных и выходных данных задачи, включим в
состав параметров процедуры дополнительный параметр, соответствующий варианту решения. В
зависимости от значения этого параметра после вызова процедуры будет выводиться соответствующий вариант результатов.
Тогда абстракция A0.3 уровня 0 детализируется следующим образом:
A0.3a <Решение задачи с фиксацией варианта решения>
A0.3b <Анализ варианта решения и вывод по соответствующему образцу>
Разработка процедуры для задачи А0.3a выполняется обычным образом и приведена ниже.
1. Задача А0.3a
Если в одномерном целочисленном массиве b есть хотя бы два одинаковых элемента, то заменить первую строку матрицы a , все элементы которой больше нуля, на этот массив, иначе найти
максимальное значение минимальных элементов строк матрицы.
2. Входные данные
цел n - число элементов массива b; число столбцов матрицы a; простая переменная;
цел m - число строк матрицы a; простая переменная;
цел b - исходный одномерный массив;
цел a - исходная матрица; двумерный массив.
Данные во внутреннем представлении (так как к моменту решения задачи А0.1 они введены);
входная форма отсутствует.
3. Выходные данные
цел a - измененная матрица;
цел maxmin - максимальное значение минимальных элементов строк; простая переменная.
Тема ?. Использование библиотек DLL.
Файл 446966401
С. 4 из 9
цел resvar – вариант решения;
resvar =
1, изменение матрицы;
2, поиск максимального значения минимальных элементов строк матрицы;
3, обработка не производится (ситуация, когда в массиве b есть хотя бы два одинаковых элемента, но в матрице нет строки со всеми положительными элементами)
Оформление процедуры
 Вид - общего вида
 Имя – reshenie
Поскольку процедура вызывается один раз, выберем для формальных параметров те же имена,
что и для фактических.
• Заголовок - проц reshenie (n, m, b,a, maxmin, resvar);
 Обращение - reshenie (n, m, b,a, maxmin, resvar);
• Описание на псевдокоде
{поиск строки со всеми положит. элементами в матрице}
проц reshenie (n, m, b,a, maxmin, resvar);
арг
цел n, m; цел b(n), a(m,n);
рез
цел a(m,n); цел maxmin, resvar;
нач
<описания локальных переменных>
<алгоритм тела процедуры>
кон;
кон reshenie;
Разработка заглушки
 Алгоритм заглушки (тело процедуры)
Для теста 1.1 (в массиве b есть два равных элемента и искомая строка есть):
{Измененная матрица}
a[1,1]:= -1; a[1,2]:= 0; a[1,3]:=2; a[1,4]:= -3;
a[2,1]:= 2; a[2,2]:= -1; a[2,3]:=0; a[2,4]:= 2;
a[3,1]:= 1; a[3,2]:= 2; a[3,3]:=3; a[3,4]:= 1;
resvar:=1;
Для теста 1.2 (в массиве b нет равных элементов):
{ Максимальное значение минимальных элементов строк матрицы }
maxmin:=1;
resvar:=2;
Для теста 1.3 (в массиве b есть два равных элемента, но искомой строки нет):
{ Обработка не производится }
resvar:=3;
Кодирование процедуры на паскале
 Определение глобальных объектов
Глобальный тип и константы для параметров a и b определены при кодировании процедур проверки массивов:
const
nmax=50;
mmax=50;
type
arrb=array[1..nmax] of integer;
arra=array[1..mmax, 1..nmax] of integer;
Тема ?. Использование библиотек DLL.
Файл 446966401
С. 5 из 9
 Описание процедуры
procedure reshenie (n,m :integer; var b:arrb; var a:arra; var maxmin: integer; var resvar: byte);
var
<описания локальных переменных>;
begin
<операторы>
end;
 Обращение к процедуре:
reshenie (n,m, b, a, maxmin, resvar);
2.2. Структура и содержание библиотеки
Пусть создаваемая библиотека имеет имя TopDownDLL.dll.
Только для консольного варианта с иллюстративной целью в библиотеку внесены еще процедуры
проверки массивов. Для корректной локализации описаний файловые переменные выходных
файлов, куда записывается диагностика ошибок, включены в список параметров (в исходном варианте процедуры были внутренними, а файловые переменные передавались как глобальные).
Текст файла проекта библиотеки TopDownDLL.dpr приведен ниже.
library TopDownDLL;
uses
SysUtils,
Classes;
{$R *.res}
{описания констант и типов, глобальных для процедур}
const
nmax=50;
mmax=50;
type
arrb=array[1..nmax] of integer;
arra=array[1..mmax,1..nmax] of integer;
{описания процедур}
{проверка массива b}
procedure provb(n:integer; var b:arrb; var bver:boolean; var res:text);
var i:byte; {локальная величина}
begin
.......
end;
{проверка массива a}
procedure prova(m, n:integer; var a:arra; var aver:boolean; var res:text);
var i,j:byte; {локальная величина}
begin
......
end;
{Решение. Вместо обработки заглушки}
procedure reshenie (n,m :integer; var b:arrb; var a:arra; var maxmin: integer; var resvar: byte);
var
{<описания локальных переменных>};
begin
.....
end;
exports //список экспортируемых функций
provb,
prova,
reshenie;
begin
end.
Тема ?. Использование библиотек DLL.
Файл 446966401
С. 6 из 9
2.3. Использование библиотеки в консольном варианте приложения
Выделены изменения в программе с комментариями.
program top_down (dat, res);
{$APPTYPE CONSOLE}
uses
SysUtils;
const
nmax=50;
mmax=50;
type
arrb=array[1..nmax] of integer;
arra=array[1..mmax,1..nmax] of integer;
var
n,m, maxmin, i, j :integer;
b:arrb;
a: arra;
nver, mver, bver, aver :boolean; {результаты анализа данных}
dat,res:text;
resvar:byte; {вариант решения}
{проверка массива b: процедура загружается из библиотеки TopDownDLL.dll}
procedure provb(n:integer; var b:arrb; var bver:Boolean; var res:text);
external 'TopDownDLL.dll';
{проверка массива a: процедура загружается из библиотеки TopDownDLL.dll}
procedure prova(m, n:integer; var a:arra; var aver:Boolean; var res:text);
external 'TopDownDLL.dll';
{ Решение задачи с фиксацией варианта решения }
procedure reshenie (n,m :integer; var b:arrb; var a:arra; var maxmin: integer; var resvar: byte);
external 'TopDownDLL.dll';
begin
{ TODO -oUser -cConsole Main : Insert code here }
assign (dat,paramstr(1)); reset(dat);
assign (res,paramstr(2)); rewrite(res);
{вывод по обр1}
writeln(res,' Задача top_down. Обработка матрицы ');
{ввод, анализ, входных данных}
{проверка n}
readln(dat,n); writeln(res,' Исходный массив b из ', n:2, ' элементов:'); { ввод- вывод n }
nver:=true;
if (n<=0) or (n>=50) then {n неверно}
begin
nver:=false; writeln(res,' n задано неверно '); {вывод по обр 4.1}
end;
if nver {n верно} then
begin
for i:=1 to n do { ввод(b(i),i=1,n) }
read(dat,b[i]);
for i:=1 to n do { вывод(b(i),i=1,n) по обр 2.2 }
write(res,' ',b[i]:3);
writeln(res);
{ А0.1. проверка массива b} {вх.:n,b; вых.:bver}
provb(n,b,bver,res);
end;
if (nver and bver) then {предыдущие данные верны}
begin
{ввод(m); вывод(m,n)по обр 2.3}
readln(dat,m); writeln(res,' Исходная матрица ', m:2, ' х', n:2, ': ');
{проверка m}
mver:=true;
if (m<=0) or (m>50) then {m неверно}
begin
mver:=false; writeln(res,' m задано неверно '); {вывод по обр 4.3}
end;
Тема ?. Использование библиотек DLL.
Файл 446966401
С. 7 из 9
end;
if (nver and bver and mver) then{предыдущие данные верны}
begin
{ ввод((a(i,j),j=1,n),i=1,m); вывод((a(i,j),j=1,n),i=1,m)по обр 2.4; }
for i:=1 to m do
begin
for j:=1 to n do
read(dat, a[i,j]);
readln(dat);
end;
for i:=1 to m do
begin
for j:=1 to n do
write (res,' ',a[i,j]:3);
writeln(res);
end;
{А0.2. проверка массива а} {вх.:m,n,a; вых.: aver}
prova(m,n,a,aver,res);
end;
if (nver and mver and bver and aver) then {все данные верны}
begin
{A0.3a Решение задачи с фиксацией варианта решения}
reshenie (n,m, b, a, maxmin, resvar);
writeln (res, ' Результаты');
{A0.3b Анализ варианта решения и вывод по соответствующему образцу} {Заглушки}
case resvar of
1: writeln (res, ' Измененная матрица');
2: writeln (res, ' Максимальное значение минимумов строк матрицы');
3: writeln (res, ' Матрица не меняется');
end;
end
else {хотя бы одно данное неверно}
writeln(res,' Задача не решалась'); { вывод по обр.4.5; }
close(dat); close(res);
end.
2.4. Использование библиотеки в варианте с графическим интерфейсом
Приводится только часть модуля, вызывающего процедуру решения.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids,
Spin;
const
nmax=50;
mmax=50;
type
TForm1 = class(TForm)
SpinEdit1: TSpinEdit; // n - число элементов массива b и столбцов матрицы a
StringGrid1: TStringGrid; //таблица для ввода массива b
SpinEdit2: TSpinEdit; // m - число строк матрицы a
StringGrid2: TStringGrid; //таблица для ввода матрицы a
Label1: TLabel; //Заголовок "Число n элементов массива B:"
Label2: TLabel; //Заголовок "Исходный массив B из n элементов:"
Label3: TLabel; //Заголовок "Число m строк матрицы A"
Label4: TLabel; //Заголовок "Исходная матрица A m x n"
Label5: TLabel; //Заголовок "Задача top_down. Обработка матрицы"
Label6: TLabel; //Сообщение "Число элементов задано неверно!"
Label7: TLabel; //Сообщения об ошибочных элементах массива B
Button1: TButton; //Кнопка "Решить"
Тема ?. Использование библиотек DLL.
Файл 446966401
С. 8 из 9
procedure SpinEdit1Change(Sender: TObject);
procedure SpinEdit1Exit(Sender: TObject);
procedure StringGrid1Exit(Sender: TObject);
procedure SpinEdit2Exit(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
arrb=array[1..nmax] of integer;
arra=array[1..mmax,1..nmax] of integer;
var
Form1: TForm1; //Форма для ввода и анализа входных данных
implementation
uses Unit2; // Unit2 содержит форму для вывода результатов
{$R *.dfm}
procedure reshenie (n,m :integer; var b:arrb; var a:arra; var maxmin: integer; var resvar: byte);
external 'TopDownDLL.dll';
//Ввод и проверка n с выводом сообщения при наличии ошибки
procedure TForm1.SpinEdit1Change(Sender: TObject);
begin
........
end;
//Формирование таблицы для ввода массива b и столбцов таблицы для ввода матрицы a
procedure TForm1.SpinEdit1Exit(Sender: TObject);
var i:integer;
begin
.......
end;
//Проверка элементов массива b при передаче фокуса ввода следующему компоненту
procedure TForm1.StringGrid1Exit(Sender: TObject);
var
i:byte;
begin
........
end;
//Формирование таблицы для ввода матрицы a
procedure TForm1.SpinEdit2Exit(Sender: TObject);
var i,j:integer;
begin
...............
end;
//Решение
procedure TForm1.Button1Click(Sender: TObject);
var
n,m, maxmin, i, j :integer;
b: arrb;
a: arra;
resvar: byte;
begin
if label7.Visible=false then
begin
//Вывод входных данных в выходную форму Form2
Тема ?. Использование библиотек DLL.
Файл 446966401
С. 9 из 9
.........................
//Преобразование входных данных из строк в числа
.............................
//Решение задачи с выводом результатов в Form2
{A0.3a Решение задачи с фиксацией варианта решения}
reshenie (n,m, b, a, maxmin, resvar);
{A0.3b Анализ варианта и вывод п соотаветствующему образцу}
case resvar of
1: Form2.label4.visible:=true; //writeln (res, ' Измененная матрица');
//2: writeln (res, ' Максимальное значение минимумов строк матрицы');
//3: writeln (res, ' Матрица не меняется');
end;
Form2.Visible:=true;
Form1.Visible:=false;
end;
end;
end.
Download