Разработка анализатора спектра ультразвукового сигнала

Автор работы: Пользователь скрыл имя, 17 Мая 2012 в 18:17, дипломная работа

Описание

Целью является расширить функциональные возможности ультразвукового акустического тракта «ТРАК», посредством разработки программного модуля, реализующего обмен данными с IBM PC и анализ спектра получаемого сигнала.

Содержание

Введение

1
Ультразвуковая дефектоскопия


1.1 Теневой метод ультразвуковой дефектоскопии


1.2 Эхо - импульсный метод ультразвуковой дефектоскопии


1.3 ''ТРАК'' Акустический модуль

2
Параллельный интерфейс: LPT-порт


2.1 Традиционный LPT-порт

3
Язык программирования - Delphi


3.1 Функциональные задачи при конструировании интерфейса


3.2 Разработка DLL в среде Borland Delphi

4
Теоретический анализ существующих алгоритмов спектрального анализа.


4.1 Задача спектрального оценивания


4.2 Преобразование Фурье


4.3 Быстрое преобразование Фурье


Заключение


Список использованных источников


Приложение А


Приложение Б


CD-диск

Работа состоит из  1 файл

диплом 22.06.doc

— 998.50 Кб (Скачать документ)

 

3.2.1 Экспорт функций из DLL

 

Для экспорта процедур и функций из DLL, необходимо использовать ключевое слово export. Еще раз обратим внимание на представленный листинг библиотеки MiFirstDll – рисунок 1. Поскольку процедура HelloWorld определена как экспортируемая, то она может быть вызвана на выполнение из других библиотек или приложений. Существуют следующие способы экспорта процедур и функций: экспорт по имени и экспорт по порядковому номеру.

Наиболее распространенный способ экспорта - по имени, описан в программе 2.

Программа 2

exports

SayHello,

DoSomething,

DoSomethingReallyCool;

 

Delphi автоматически назначает порядковый номер каждой экспортируемой функции (процедуре) независимо от того, определяем его явно или нет. Явное определение индекса позволяет управлять порядковым номером экспортируемой функции или процедуры.

Для того чтобы определить выполняется ли кодек в DLL или в вызывающем приложении, можно воспользоваться глобальной переменной IsLibrary. Она принимает значение true в том случае, если код вызывается из библиотеки и false в случае выполнения процедуры или функции из вызывающего приложения.

Кроме этого, в поставку Delphi входит весьма полезная утилита tdump, которая предоставляет данные о том, какая информация экспортируется из указанной DLL.

 

3.2.2 Использование DLLProc

 

Код инициализации динамической библиотеки может быть помещен в блок begin...end. Однако кроме этого зачастую необходимо предусмотреть некоторые действия, выполняемые в процессе выгрузки DLL из оперативной памяти. В отличии от других типов модулей, модуль DLL не имеет ни секции initialization, ни секции finalization. К примеру, можем динамически выделить память в главном блоке, однако не понятно, где эта память должна быть освобождена. Для решения этой проблемы существует DLLProc - специальная процедура, вызываемая в определенные моменты функционирования DLL.

Для начала следует сказать о самой причине существования DLLProc. Динамическая библиотека получает сообщения от Windows в моменты своей загрузки и выгрузки из оперативной памяти, а также в тех случаях, когда какой-нибудь очередной процесс, использующий функции или ресурсы, хранящиеся в библиотеке, загружается в память. Такая ситуация возможно в том случае, когда библиотека необходима для функционирования нескольких приложений. А для того, чтобы имели возможность указывать, что именно должно происходить в такие моменты, необходимо описать специальную процедуру, которая и будет ответственна за такие действия. К примеру, она может выглядеть следующим образом, как описано в программе 3.

Программа 3

procedure MyFirstDLLProc(Reason: Integer);

begin

        if Reason = DLL_PROCESS_DETACH then

        {DLL is unloading. Cleanup code here.}

end;

 

Однако системе совершенно не очевидно, что именно процедура MyFirstDllProc, ответственная за обработку рассмотренных выше ситуаций. Поэтому должны поставить в соответствие адрес процедуры глобальной переменной DLLProc. Это необходимо сделать в блоке begin...end, как описано в программе 4.

Программа 4

begin

Окончание программы 4

DLLProc := @MyDLLProc;

{ Что-нибудь еще, что должно выполняться в

процессе инициализации библиотеки }

end.

 

Код, демонстрирующий один из возможных вариантов применения DLLProc, описан в программе 5.

Программа 5

library MyFirstDLL;

uses

        SysUtils,

        Classes,

        Forms,

        Windows;

var

        SomeBuffer : Pointer;

procedure MyFirstDLLProc(Reason: Integer);

begin

        if Reason = DLL_PROCESS_DETACH then

        {DLL is выгружается из памяти.

         Освобождаем память, выделенную под буфер.}

        FreeMem(SomeBuffer);

end;

procedure HelloWorld(AForm : TForm);

begin

        MessageBox(AForm.Handle, Hello world!',

        DLL Message Box', MB_OK or MB_ICONEXCLAMATION);

Окончание программы 5

end;

{Какой-нибудь код, в котором используется SomeBuffer.}

 

exports

        HelloWorld;

begin

        {Ставим в соответствие переменной

        DLLProc адрес нашей процедуры.}

        DLLProc := @MyFirstDLLProc;

        SomeBuffer := AllocMem(1024);

end.

 

В качестве признака того или иного события, в результате которого вызывается процедура MyFirstDll, является значение переменной Reason. Ниже приведены возможные значения этой переменной:

-DLL_PROCESS_DETACH - библиотека выгружается из памяти; используется один раз;

-DLL_THREAD_ATTACH - в оперативную память загружается новый процесс, использующий ресурсы и/или код из данной библиотеки;

-DLL_THREAD_DETACH - один из процессов, использующих библиотеку, "выгружается" из памяти.

 

3.2.3 Загрузка DLL

 

Прежде чем начать использование какой-либо процедуры или функции, находящейся в динамической библиотеке, необходимо загрузить DLL в оперативную память. Загрузка библиотеки может быть осуществлена одним из двух способов: статическая загрузка и динамическая загрузка. Оба метода имеют как преимущества, так и недостатки.

Статическая загрузка означает, что динамическая библиотека загружается автоматически при запуске на выполнение использующего ее приложения. Для того чтобы использовать такой способ загрузки, необходимо воспользоваться ключевым словом external при описании экспортируемой из динамической библиотеки функции или процедуры. DLL автоматически загружается при старте программы, сможем использовать любые экспортируемые из нее подпрограммы точно так же, как если бы они были описаны внутри модулей приложения. Это наиболее легкий способ использования кода, помещенного в DLL. Недостаток метода заключается в том, что если файл библиотеки, на который имеется ссылка в приложении, отсутствует, программа откажется загружаться.

Смысл динамического метода заключается в том, что загружаем библиотеку не при старте приложения, а в тот момент, когда вам это действительно необходимо. Если функция, описанная в динамической библиотеке, используется только при 10 % запусков программы, то совершенно нет смысла использовать статический метод загрузки. Выгрузка библиотеки из памяти в данном случае также осуществляется под контролем. Еще одно преимущества такого способа загрузки DLL - это уменьшение времени старта приложения. Основной недостаток - это то, что использование данного метода является более хлопотным, чем рассмотренная выше статическая загрузка. Сначала необходимо воспользоваться функцией Windows API LoadLibrary. Для получения указателя на экспортируемой процедуры или функции должна использоваться функция GetProcAddress. После завершения использования библиотеки DLL должна быть выгружена с применением FreeLibrary.

 

3.2.4 Вызов процедур и функций, загруженных из DLL

 

Способ вызова процедур и функций зависит от того, каким образом загрузили динамическую библиотеку, в которой эти подпрограммы находятся. Вызов функций и процедур из статически загруженных DLL достаточно прост. Первоначально в приложении должно содержаться описание экспортируемой функции (процедуры). После этого можно их использовать точно так же, как если бы они были описаны в одном из модулей приложения. Для импорта функции или процедуры, содержащейся в DLL, необходимо использовать модификатор external в их объявлении. К примеру, для рассмотренной процедуры HelloWorld в вызывающем приложении должна быть помещена следующая строка, описанная в программе 6.

Программа 6

procedure SayHello(AForm : TForm); external myfirstdll.dll';

 

Ключевое слово external сообщает компилятору, что данная процедура может быть найдена в динамической библиотеке. Далее вызов этой процедуры, описан в программе 7.

Программа 7

...

HelloWorld(self);

...

 

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

Импорт из DLL может проводиться по имени процедуры (функции), порядковому номеру или с присвоением другого имени.

В первом случае просто объявляем имя процедуры и библиотеку, из которой ее импортируете. Импорт по порядковому номеру требует  указание этого  номера, описанного в программе 8.

Программа 8

procedure HelloWorld(AForm : TForm);

external myfirstdll.dll' index 15;

 

В этом случае имя, которое даем процедуре при импорте не обязательно должно совпадать с тем, которое было указано для нее в самой DLL. Т.е. приведенная означает, что импортируем из динамической библиотеки myfirstdll.dll процедуру, которая в ней экспортировалась пятнадцатой, и при этом в рамках приложения этой процедуре дается имя SayHello. Если по каким-то причинам не применяем описанный способ импорта, как описано в программе 8, но тем не менее хотим изменить имя импортируемой функции (процедуры), то можно воспользоваться третьим методом, описанным в программе 9.

Программа 9             

procedure CoolProcedure;

external myfirstdll.dll' name DoSomethingReallyCool';

 

Здесь импортируемой процедуре CoolProcedure дается имя DoSomethingReallyCool. Вызов процедур и функций, импортируемых из динамически загружаемых библиотек несколько более сложен, чем рассмотренный способ, описанный в программе 9. В данном случае требуется объявить указатель на функцию или процедуру, которую  собираемся использовать. Во-первых, необходимо объявить тип, который описывал бы эту процедуру, описанный в программе 10.

Программа 10

type

THelloWorld = procedure(AForm : TForm);

 

Теперь необходимо загрузить динамическую библиотеку, с помощью GetProcAddress получить указатель на процедуру, вызвать эту процедуру на выполнение, и, наконец, выгрузить DLL из памяти. Код, описанный в программе 11.

Программа 11

var

        DLLInstance : THandle;

        HelloWorld : THelloWorld;

begin

        { загружаем DLL }

        DLLInstance := LoadLibrary(myfirstdll.dll');

        { получаем указатель }

        @HelloWorld := GetProcAddress(DLLInstance, HelloWorld');

        { вызываем процедуру на выполнение }

        HelloWorld(Self);

        { выгружаем DLL из оперативной памяти }

        FreeLibrary(DLLInstance);

end;

 

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

 

 

Программа 12

procedure TForm1.DynamicLoadBtnClick(Sender: TObject);

type

        THelloWorld = procedure(AForm : TForm);

var

        DLLInstance : THandle;

        HelloWorld : THelloWorld;

begin

        DLLInstance := LoadLibrary(myfirstdll.dll');

        if DLLInstance = 0 then begin

                MessageDlg(Невозможно загрузить DLL', mtError, [mbOK], 0);

                Exit;

        end;

        @HelloWorld := GetProcAddress(DLLInstance, HelloWorld');

        if @HelloWorld <> nil then

                HelloWorld (Self)

        else

                MessageDlg(Не найдена искомая процедура!.', mtError, [mbOK], 0);

        FreeLibrary(DLLInstance);

end;

 

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

Создадим новый проект динамической библиотеки. Для этого выберем пункт меню File|New, а затем дважды щелкнем на иконку DLL. После этого  увидим следующий код, описанный в программе 13.

Программа 13

library Project2;

{здесь были комментарии}

 

uses

        SysUtils,

        Classes;

 

{$R *.RES}

 

begin

end.

 

Полученный проект назовем  DllForms.dpr.

Теперь следует создать новую форму. Это можно сделать по-разному. Например, выбрав пункт меню File|New Form. Добавим на форму какие-нибудь компоненты. Назовем форму DllForm и сохраним получившийся модуль под именем DllFormUnit.pas.

Вернемся к главному модулю проекта и поместим в него функцию ShowForm, в задачу которой будет входить создание формы и ее вывод на экран. Используем для этого код, описанный в программе 14.

Информация о работе Разработка анализатора спектра ультразвукового сигнала