Содержание
Здесь содержится информация о расширениях пакета CrwDaq.
Расширения (плагины, утилиты) могут быть весьма полезными, т.к. позволяют использовать высокую скорость и огромные возможности натурального кода, создаваемого с помощью компилятора Free Pascal.
Под расширениями здесь понимаются исполняемые программные модули пакета, которые не входятв основной исполняемый файл пакета, а существуют в виде отдельных файлов. Расширениями пакета считаются программные модули, специально разработанные для работы в составе пакета, а не сторонние программы, которые разрабатывались для других целей, но были включены в пакет ввиду их полезности. Различие состоит в том, что расширения пакета делаются по определенным правилам, с учетом возможности взаимодействия с основным пакетом.
Расширения делятся на два основных класса:
Плагины (plugin) - динамически
загружаемые модули в виде библиотек *.dll
или lib*.so, которые загружаются по мере
необходимости и работают в адресном пространстве основного исполняемого
файла пакета.
Утилиты (utility) - автономные программы (как правило, консольные), выполняющие четко определенную (утилитарную) задачу, запускаемые из среды пакета и работающие параллельно с пакетом для решения общей задачи управления.
Все расширения пишутся в среде пакета crwdaq на Free Pascal, по шаблонам. Компилятор Free Pascal интегрирован с пакетом, хотя устанавливается отдельно. Редактирование, компиляция и запуск расширений деляется из среды пакета crwdaq.
Подробнее см. типы расширений.
Расширения пакета делятся на такие типы:
Плагины dan - загружаемые
расширения для анализа данных (dan - data analysis
plugin).
Эти плагины привязаны к окнам с данными (графиками кривых) и служат для
обработки данных.
Их вызов происходит по команде пользователя.
Плагины daq - загружаемые
расширения для сбора данных (daq - data acquisition
plugin).
Эти плагины привязаны к устройствам (device) системы сбора
данных DAQ.
Их загрузка и выгрузка происходит вместе с конфигурацией
DAQ-системы.
Их вызов происходит в цикле опроса в процессе работы
DAQ-системы.
За загрузку/выгрузку/опрос отвечает программа-владелец
DaqPascal,
с помощью вызовов DaqDllInit,
DaqDllFree, DaqDllCall.
Консольные драйверы - автономные
присоединенные консольные программы.
Обычно это драйверы или серверы,
работающие в составе DAQ-систем,
запускаемые клиентской программой DaqPascal и
подключенные к этой клиентской
программе через анонимный канал связи. Через этот канал клиентская
программа
DaqPascal передает команды и получает данные от
сервера.
Можно образно сказать, что присоединенные консольные драйверы - это
программы на коротком поводке.
Консольные утилиты - автономные
отсоединенные программы разного назначения.
Обычно эти они работают в составе DAQ-систем, но могут
быть полезными и для других целей.
Эти программы не подключаются через канал связи, и работают без прямого
контроля со стороны пакета.
Они, например, могут запускаться автономно и работать в фоновом режиме
для обработки данных.
При этом запускаемые из пакета утилиты сохряняют с ним некоторую связь,
т.к. наследуют окружение.
Через это окружение они могут взаимодействовать с основным пакетом,
посылая ему сообщения.
Например, они могут по завершении обработки уведомить пакет о
результатах работы посылкой сообщения
командой unix send2crwdaq … в
Главную Консоль пакета.
Можно образно сказать, что отсоединенные консольные утилиты - это
программы на свободном выпасе.
Плагины - это загружаемые динамические библиотеки с кодом, построенным по определенным правилам.
Плагин оформляется в виде динамической библиотеки
*.dll или
lib*.so.
Библиотека загружается по требованию пользователя и создается на языке
Free Pascal.
Библиотека экспортирует одну функцию
плагина:
function CRWDAQ_PLUGIN(CrwApi:ICrwApi):Integer;
Функция принимает аргумент CrwApi -
интерфейс ICrwApi для доступа к
пакету.
Переданный экземпляр интерфейса содержит в себе большой список (около
1000) функций.
В совокупности эти функции содержат в себе библиотеку для доступа к
данным вызывающего пакета.
Интерфейс описан в модуле _crw_crwapi.pas.
Всё взаимодействие плагина с вызывающим пакетом выполняется с
помощью функций интерейса ICrwApi.
Ввод-вывод также обеспечивается функциями этого интерфейса.
Функция плагина при вызове выполняет требуемую работу и
возвращает как результат статус операции:
обычно 0 при успехе или ненулевой код ошибки при
возникновении проблем.
Интерфейс ICrwApi описан в модуле _crw_crwapi.pas.
В основном он содержит функции идентификации и другие (предметные)
интерфейсы.
Некоторые важные методы ICrwApi приведены в следующей
таблице:
| Методы ICrwApi | Описание |
|---|---|
| Version:Cardinal | Версия API плагина в виде числа - даты вида 20241121. |
| Target:Cardinal | Целевой контекст вызова: ForDataAnalysis, ForDataAcquisition. |
| SysApi:ISysApi | Интерфейс с набором системных (system) функций общего назначения. |
| GuiApi:IGuiApi | Интерфейс с функциями графического интерфейса пользователя (GUI). |
| DanApi:IDanApi | Интерфейс с функциями анализа данных (data analusis) в окне с кривыми. |
| DaqApi:IDaqApi | Интерфейс с функциями сбора данных (data acquisition) и управления. |
| PluginName:LongString | Короткое имя плагина. |
| PluginSourceFileName:LongString | Полное имя файла исходного кода .lpr плагина. |
| PluginBinaryFileName:LongString | Полное имя исполняемого файла
*.dll/lib*.so
плагина. |
Метод Target служит для опрелеления целевого контекста вызова. Если он равен ForDataAnalysis, то это вызов обработки данных, находящихся в окне с кривыми. В этом случае надо использовать интерфейс DanApi для достура к данным окна. Если же метод Target вернул ForDataAcquisition, то это вызов из DAQ-системы сбора данных. В этом случае надо использовать интерфейс DaqApi для доступа к данным DAQ-системы.
Методы Version, PluginName, PluginSourceFileName, PluginBinaryFileName служат для идентификации плагина, позволяя определять его точное расположение, название и т.д. Это може помочь, например, для диагностики или для поиска дополнительных файлов или ресурсов.
Методы CrwApi.SysApi, CrwApi.GuiApi содержат большое число функций общего назначения, которые можно использовать для решения задач, выполняемых плагином.
Полный список и описание интерфейсов, классов, функций, переменных, констант модуля
_crw_crwapiс описанием интерфейса ICrwApi подключения плагинов см. тут или там.
При создании плагинов следует соблюдать высокую дисциплину программирования. Дело в том, что плагины загружаются и работают в адресном пространстве вызывающего их пакета. Это дает высокую скорость работы плагинов, но одновременно повышает ответственность программиста. Все ошибки в коде плагина могут иметь непосредственное влияние на работу пакета. После выгрузки плагина все не освобожденные им ресурсы становятся “потерянными”, т.е. возникает утечка ресурсов.
Поэтому программировать плагины надо очень аккуратно и ответственно.
Все занятые ресурсы (память, файлы, объекты) надо вовремя
освобождать.
Рекомендуется при выделении ресурсов использовать конструкцию
try … finally … end; для гарантированного освобождения
ресурсов.
Стараться избегать длительных циклов ожидания, чтобы не “подвесить” основной пакет.
Не надо жалеть времени на проверки, позволяющие заранее избегать
аварийных ситуаций.
Своевременная проверка аргументов и условий позволит предотвратить
исключения до их возможного возникновения.
Надо стараться перехватывать и обрабатывать исключения
try … except … end;.
Хотя код вызова перехватывает исключения, все же лучше делать это в
самом плагине.
По мере возможности следует ограничивать число используемых
(uses) модулей.
Максимальное использование функций ICrwApi позволяет
решать большое число задач без привлечения других модулей. Проблема
модулей в том, что они могут содержать коды инициализации и завершения,
после которых могут оставаться неосвобожденные ресурсы (после выгрузки
плагина из памяти).
Плагины для обработки данных dan - data analysis
plugin - это динамически загружаемые библиотеки
*.dll или
lib*.so, загружаемые по команде
пользователя для выполнения обработки данных в окне с графиками кривых.
Эти плагины привязаны к окнам с данными (графиками кривых) и служат для
обработки данных, которые в этих окнах содержатся. Их вызов происходит
по команде пользователя - обычно по кнопке
.
Плагины обработки данных пишутся по определенному шаблону на языке Free Pascal. Написанный или отредактированный в среде пакета плагин затем можно сразу скомпилировать, а затем загрузить и исполнить. Это делает пакет crwdaq саморасширяемой средой разработки и исполнения, позволяющей прикладному программисту самостоятельно дополнять пакет разработанными средствами, если имеющихся средств не хватает.
Плагины обработки данных находятся в папке resource/plugin/dan/.
запуска плагина в окне с графиками кривых.Рассмотрим протейший плагин обработки данных _curve_integral, выполняющий интегрирование (вычисление первообразной):
Разберем приведенный выше плагин подробнее.
Плагин обработки данных должен иметь чёткую структуру, описанную ниже.
В начале кода идет помещенный в комментариях блок секций Русской/Английской справки - [Manual.Rus]/[Manual.Eng], а также секций аргументов на Русском/Агнглийском [Arguments.Rus]/[Arguments.Eng].
{
[Manual.Rus]
…
[Manual.Eng]
…
[Arguments.Rus]
Имя окна = …
Заголовок = …
Легенда = …
[Arguments.Eng]
Caption = …
Title = …
Legend = …
}Справка отображаются в диалоге вызова плагина для пояснения того, что
он делает.
Аргументы - это редактируемые в диалоге параметры, нужные для проведения
расчетов.
Значения аргументов извлекаются вызовами типа
GetArgumentAsString(RusEng('Имя окна','Caption'));.
Примерный вид диалога вызова плагина обработки данных приведен на следующем рисунке:
| Команда | Действие | Комментарий |
|---|---|---|
![]() |
Запуск | Запуск выбранного плагина на выполнение. |
![]() |
Изменить | Открыть окно редактирования плагина. |
![]() |
Удалить | Удалить выбранный плагин. |
![]() |
Клонировать | Клонировать выбранный плагин в новый. |
![]() |
Компилировать | Компилировать выбранный плагин. |
![]() |
Компил-ть Все | Компилировать все доступные плагины. |
![]() |
Выход | Закрыть диалог запуска плагинов. |
После блока справки и аргументов идет объявление библиотеки
library …;, затем
обязательная вставка общих определений {$I
_crw_sysdef.inc}](../../../crwlib/_crw_sysdef.inc)** и режима компиляции
**[{$I _crw_sysmode.inc}.
library _curve_integral;
{$I _crw_sysdef.inc}
{$I _crw_sysmode.inc}Этот блок кода обязателен, т.к. он задает необходимые режимы компиляции.
После определений и режимов компиляции обязательно
идет блок uses:
uses
//////////////////////////////////////////////////////
{$I _crw_uses_first.inc} // NB: MUST BE FIRST USES !!!
//////////////////////////////////////////////////////
sysutils, classes, math, graphics,
_crw_crwapi;Очень важно соблюдать следующие правила:
_crw_crwapi.Минимизация списка используемых модулей необходима по следующей
причине.
Плагин должен освобождать все занятые ресурсы, т.к. библиотека с кодом
плагина загружается динамически и затем освобождается. Прикладной код
должен освобождать все (явно) занятые ресурсы, однако при использовании
модулей при загрузке библиотек будут неявно (скрыто) выполняться код
initialization модуля при загрузке и
finalization при выгрузке библиотеки. Далеко не все
библиотеки написаны чисто в смысле освобождения
ресурсов. Это связанос тем, что модули чаще всего ориентируются на
исполняемые приложения *.exe, а не на
библиотеки. Освобождать все ресурсы в конце работы программы не столь
необходимо, т.к. программа всё равно уже завершается. А вот при выгрузке
библиотек выполнение программы продолжается. Всё, что не освободил любой
из модулей библиотеки, будет утечкой ресурсов. Поэтому
число модулей uses нужно по возможности
минимизировать.
Интерфейс CrwApi, переданный в плагин при его вызове, содержит в себе порядка 1000 функций, дающих доступ к библиотеке crwlib, уже скомпилированных в ядре пакета. Поэтому для плагинов крайне желательно по мере возможности ограничиться этим набором вместо подключения дополнительных модулей. Это не только сократит объем кода плагина (т.к. вместо компиляции нового кода интерфейс ссылается на уже скомпилированный код), но и сократит использование ресурсов (которые уже выделены в коде пакета). А главное, будет меньше проблем с освобождением ресурсов, занятых модулями, а потому меньше вероятность утечки памяти.
После uses необходим блок декларации функции плагина.
/////////////////////////////////////////////////////////
{$I _crw_plugin_declare.inc} // Declare CRWDAQ_PLUGIN. //
/////////////////////////////////////////////////////////
// function CRWDAQ_PLUGIN(CrwApi:ICrwApi):Integer; //
/////////////////////////////////////////////////////////Для обеспечения централизации и единства кода декларация делается с помощью включаемого файла {$I _crw_plugin_declare.inc}. Это позволяет управлять кодом декларации всех плагинов в одном файле. А также обеспечивает правильность декларации во всех плагинах. Заметим, что плагин использует соглашение о вызовах ABI call (application binary interface), заданное в файле _crw_plugin_abicall.inc.
После декларации функции плагина следует тело плагина, т.е. его содержательная часть.
В начале этого блока следует:
with CrwApi,SysApi,GuiApi,DanApi do для
доступа к методам библиотеки,Это выглядит примерно так:
begin
Result:=0;
with CrwApi,SysApi,GuiApi,DanApi do
try
RedirectStdIn(Input);
RedirectStdOut(Output);
VerifyPluginDate(CrwApiEdition,Version);
VerifyPluginType(Target,ForDataAnalysis);
…
… код плагина …
…
except
on E:Exception do begin
if WindowExists(twin) then CurvesCount[twin]:=0;
Echo(PluginName+RusEng(': ОШИБКА!',': ERROR!'));
if UsesBlaster then Voice('EXCEPTION');
Echo(E.Message); Error(E.Message);
Result:=-1;
end;
end;
end;В теле плагина используются данные (кривые) из активного окна и данные из буфера обмена. Результат (новые кривые) помещается в новое окно. Кривые и окна идентифицируются целочисленными номерами: положительные числа нумеруют кривые в окне источника (source), отрицательные - приемника (target), ноль ссылается на буфер обмена (clipboard).
const
swin = +1; // Source window reference
twin = -1; // Target window reference
cwin = 0; // Clipboard window referenceНапример, вызов WindowExists(twin) проверяет наличие окна приемника, а CurvesCount[twin] - возвращает число кривых в окне приемника.
Как правило, назначение функций и их аргументов понятно из названий.
Полный список и описание интерфейсов, классов, функций, переменных, констант модуля
_crw_crwapiс описанием интерфейса ICrwApi подключения плагинов см. тут или там.
В конце, после завершения функции плагина, необходимо экспортировать её:
/////////////////////////////////////////////////////////
{$I _crw_plugin_exports.inc} // Exports CRWDAQ_PLUGIN. //
/////////////////////////////////////////////////////////
// exports CRWDAQ_PLUGIN name CRWDAQ_PLUGIN_ID; //
/////////////////////////////////////////////////////////
begin
end.Экспорт выполняется вставкой {$I _crw_plugin_exports.inc}, что обеспечивает централизованное управление кодом плагинов.
Пакет содержит большую библиотеку (более 30) готовых плагинов обработки данных dan, созданных по одному шаблону. Средства клонирования (копирования и сохранения под другим именем) позволяют создавать новые плагины, взяв существующие плагины в качестве образца (шаблона).
Плагины обработки данных, имя которых начинается с подчеркивания
_, считаются
“защищенными”. Их нельзя удалять и редактировать
средствами пакета - на них стоит блокировка. Это сделано для того, чтобы
избежать нежелательного изменения хорошо отлаженных стандартных
плагинов, которые не требуют редактирования, а используются “как есть”,
в готовом виде.
Плагины для сбора данных - daq -
data acquisition plugin - это динамически загружаемые
библиотеки *.dll или
lib*.so, загружаемые в составе
DAQ системы и работающие для решения задач сбора данных
и управления физическими установками. Эти плагины привязаны к
устройствам DAQ системы devices software
program, т.е. к программам на языке DaqPascal
и служат для сбора и обработки данных в режиме online.
Они вызываются и выполняются в контесте потока программы
DaqPascal.
Плагины обработки данных пишутся по определенному шаблону на языке Free Pascal. Написанный или отредактированный в среде пакета плагин затем можно сразу скомпилировать, а затем загрузить и исполнить в составе конфигурации DAQ-системы. Это делает пакет crwdaq саморасширяемой средой разработки и исполнения, позволяющей прикладному программисту самостоятельно дополнять пакет разработанными средствами, если имеющихся средств не хватает.
Шаблоны плагинов сбора данных находятся в папке resource/plugin/daq/. Также есть плагины сбора данных в демо конфигурациях demo_dll_min, demo_dll_sin и ряда других.
DaqDllCall(ref,cmd), где:
DaqDllInit(DllFilePath).DaqDllCall(…,DAQ_CMD_INIT), чтобы плагин
провел свою инициализацию.DaqDllCall(…,DAQ_CMD_POLL), чтобы плагин
выполнил свою процедуру опроса.DaqDllCall(…,DAQ_CMD_FREE), чтобы плагин
освободил занятые ресурсы.DaqDllFree.Загружать, освобождать и вызывать daq плагины можно в принципе из любой программы на языке DaqPascal. Это удобно делать с помощью функций стандартной библиотеки. Если использовать стандартный шаблон программы, достаточно вызвать STD_DLL_INIT при старте программы, инициировав загрузку DLL.
procedure InitApplication;
begin
…
// Initialize DAQ plugin DLL:
STD_DLL_INIT('DLL_FILE_PATH');
…
end;Дальше стандартная библиотека возьмет на себя вызов плагина в каждом цикле опроса и его освобождение в конце работы DAQ-системы.
Стандартная библиотека после вызова
STD_DLL_INIT выполняет вызов плагина к
каждом цикле опроса. Если нужна другая логика работы (например, вызов
плагина только по событиям), то лучше использовать функции DLL_INIT/FREE/POLL,
которые позволяют вызывать плагин тогда, когда требуется прикладному
алгоритму. Но и следить за логикой работы плагина тогда придется
самостоятельно.
Как уже было сказано, для вызова daq плагина требуется DAQ-программа на языке DaqPascal, которая его вызывает, так как плагин выполняется в контексте вызывающей его DAQ-программы. Код вызова daq плагина можно вставить в любую программу, однако в стандартной библиотеке есть готовая программа _dllhost.pas, которая специально предназначена для вызова daq плагина.
Программа - оболочка конфигурируется примерно так:
[DeviceList]
&DEMO_DLL_HOST = device software program
[]
[&DEMO_DLL_HOST]
InquiryPeriod = 10 ; период опроса
DevicePolling = 100, tpNormal ; период, приоритет потока
DLL_FILE_PATH = demo_dll_min_plugin\demo_dll_min_plugin.dll ; расположение DLL плагина
ProgramSource = ~~/resource/daqsite/stdlib/daqpas/_dllhost.pas ; программа-владелец(обертка)
StdIn_EnablePoll = 1 ; Разрешение опроса StdIn в коде DaqPascal, иначе опрос делает код плагина
…
… и другие параметры …
…
[]В конфигурации задается ссылка
DLL_FILE_PATH на бинарный файл плагина, а
также ссылка ProgramSource на
программу-оболочку _dllhost.pas. Также
задается флаг StdIn_EnablePoll, который
разрешает опрос консольного ввода StdIn в программе
DaqPascal. Если он сброшен в ноль, то обрабатывать
консольный ввод должен сам плагин.
Использование программы - оболочки упрощает использование daq плагинов, предоставляя готовую клиентскую часть для подключения плагина к DAQ системе.
В стандартной библиотеке есть запасная (несколько устаревшая, но вполне рабочая) готовая программа _dllwrap.pas, которая специально предназначена для вызова daq плагина.
Программа - оболочка конфигурируется примерно так:
[DeviceList]
&DEMO_DLL_MIN = device software program
[]
[&DEMO_DLL_MIN]
InquiryPeriod = 10 ; период опроса
DevicePolling = 100, tpNormal ; период, приоритет потока
DLL_FILE_PATH = demo_dll_min_plugin\demo_dll_min_plugin.dll ; распположение DLL
ProgramSource = ~~/resource/daqsite/stdlib/daqpas/_dllwrap.pas ; программа-оболочка
…
… и другие параметры …
…
[]В конфигурации задается ссылка
DLL_FILE_PATH на бинарный файл плагина, а
также ссылка ProgramSource на
программу-оболочку _dllwrap.pas.
Использование программы - оболочки упрощает использование daq плагинов, предоставляя готовую клиентскую часть для подключения плагина к DAQ системе.
Рассмотрим протейший плагин сбора данных demo_dll_min_plugin,
просто выводящий в консоль устройства синусоиду - значение
sin(omega*time):
Разберем приведенный выше плагин подробнее.
Плагин сбора данных должен иметь чёткую структуру, описанную ниже.
Первым идет объявление библиотеки
library …;, затем
обязательная вставка общих определений {$I
_crw_sysdef.inc}](../../../crwlib/_crw_sysdef.inc)** и режима компиляции
**[{$I _crw_sysmode.inc}.
library demo_dll_min_plugin;
{$I _crw_sysdef.inc}
{$I _crw_sysmode.inc}Этот блок кода обязателен, т.к. он задает необходимые режимы компиляции.
После определений и режимов компиляции обязательно
идет блок uses:
uses
//////////////////////////////////////////////////////
{$I _crw_uses_first.inc} // NB: MUST BE FIRST USES !!!
//////////////////////////////////////////////////////
sysutils, classes, math, graphics,
_crw_crwapi;Очень важно соблюдать следующие правила:
_crw_crwapi.Минимизация списка используемых модулей необходима по следующей
причине.
Плагин должен освобождать все занятые ресурсы, т.к. библиотека с кодом
плагина загружается динамически и затем освобождается. Прикладной код
должен освобождать все (явно) занятые ресурсы, однако при использовании
модулей при загрузке библиотек будут неявно (скрыто) выполняться код
initialization модуля при загрузке и
finalization при выгрузке библиотеки. Далеко не все
библиотеки написаны чисто в смысле освобождения
ресурсов. Это связанос тем, что модули чаще всего ориентируются на
исполняемые приложения *.exe, а не на
библиотеки. Освобождать все ресурсы в конце работы программы не столь
необходимо, т.к. программа всё равно уже завершается. А вот при выгрузке
библиотек выполнение программы продолжается. Всё, что не освободил любой
из модулей библиотеки, будет утечкой ресурсов. Поэтому
число модулей uses нужно по возможности
минимизировать.
Интерфейс CrwApi, переданный в плагин при его вызове, содержит в себе порядка 1000 функций, дающих доступ к библиотеке crwlib, уже скомпилированных в ядре пакета. Поэтому для плагинов крайне желательно по мере возможности ограничиться этим набором вместо подключения дополнительных модулей. Это не только сократит объем кода плагина (т.к. вместо компиляции нового кода интерфейс ссылается на уже скомпилированный код), но и сократит использование ресурсов (которые уже выделены в коде пакета). А главное, будет меньше проблем с освобождением ресурсов, занятых модулями, а потому меньше вероятность утечки памяти.
После uses необходим блок декларации функции плагина.
/////////////////////////////////////////////////////////
{$I _crw_plugin_declare.inc} // Declare CRWDAQ_PLUGIN. //
/////////////////////////////////////////////////////////
// function CRWDAQ_PLUGIN(CrwApi:ICrwApi):Integer; //
/////////////////////////////////////////////////////////Для обеспечения централизации и единства кода декларация делается с помощью включаемого файла {$I _crw_plugin_declare.inc}. Это позволяет управлять кодом декларации всех плагинов в одном файле. А также обеспечивает правильность декларации во всех плагинах. Заметим, что плагин использует соглашение о вызовах ABI call (application binary interface), заданное в файле _crw_plugin_abicall.inc.
После объявления функции плагина надо определить область данных daq плагина, обычно это тип записи TDaqDataSheet.
////////////////////////////
// Comment on TDaqDataSheet:
// Hold all DAQ data there!!
// Init all on DAQ_CMD_INIT.
// Free all on DAQ_CMD_FREE.
// Use data on DAQ_CMD_POLL.
////////////////////////////
type ////////////////////////
TDaqDataSheet = packed record
Sinus : Double;
Omega : Double;
timeSec : Double;
dllName : LongString;
end; //// TDaqDataSheet /////
////////////////////////////Запись TDaqDataSheet должна содержать
ВСЕ данные, нужные в процессе работы
daq плагина. Необходимость области данных
TDaqDataSheet связана с тем, что плагин сбора
данных, в отличие от плагина обработки данных,
вызывается многократно - в цикле опроса потока DAQ
устройства. Данные между вызовами надо где-то хранить - но не в стеке,
который освобождается после вызова. Разумно использовать для хранения
данных интерфейс CrwApi, время жизни которого глобально
- точнее, оно совпадает с временем жизни загруженного плагина. Поэтому
все данные daq плагина хранятся в буфере памяти, доступ
к которому дает функция интерфейса
CrwApi.DaqApi.DaqDataSheet(n), где n -
размер буфера памяти. При этом, если значение n
меняется, происходит перераспределение памяти. Поэтому важно, чтобы
значение n было постоянным в процессе опроса. Для этого
обычно используется конструкция
with TDaqDataSheet(DaqDataSheet(SizeOf(TDaqDataSheet))^) do …,
которая ипользует SizeOf(TDaqDataSheet)
для выделения буфера и приведение типа
TDaqDataSheet(DaqDataSheet(…)^) для
доступа к данным в буфере.
Подчеркнем еще раз - все данные плагина надо
размещать в TDaqDataSheet.
Затем эти данные надо:
DAQ_CMD_INIT,DAQ_CMD_FREE,DAQ_CMD_POLL.Клиентская часть программы DaqPascal должна обеспечить вызов этих команд в процессе работы DAQ-системы.
После декларации функции плагина следует тело плагина, т.е. его содержательная часть.
В этом блоке следует:
with CrwApi,SysApi,GuiApi,DaqApi do для
доступа к методам библиотеки,DAQ_CMD_INIT выполнить инициализацию полей
области данных DaqDataSheet:
DAQ_CMD_FREE выполнить освобождение
(очистку, удаление) данных:
DAQ_CMD_INIT,DAQ_CMD_POLL выполнить работу по сбору или
обработке данных:
На практике это выглядит примерно так:
begin
Result:=0;
with CrwApi,SysApi,GuiApi,DaqApi do
try
VerifyPluginDate(CrwApiEdition,Version);
VerifyPluginType(Target,ForDataAcquisition);
///////////////////////////////////////////////////////////////
// Nota Bene: all driver data must be located in DaqDataSheet!!
///////////////////////////////////////////////////////////////
with TDaqDataSheet(DaqDataSheet(SizeOf(TDaqDataSheet))^) do begin
case DaqCommand of
////////////////////
// Initialize driver
////////////////////
DAQ_CMD_INIT: begin
RedirectStdIn(Input);
RedirectStdOut(Output);
//////////////////////////////////////////////////
// Initialize USER data located in DaqDataSheet //
//////////////////////////////////////////////////
dllName:=ExtractFileNameExt(PluginBinaryFileName);
GuiApi.Echo(Format('Starting %s …',[dllName]));
…
… Инициализация данных TDaqDataSheet
…
//////////////////
GuiApi.Echo('Ok');
end;
//////////////////
// Finalize driver
//////////////////
DAQ_CMD_FREE: begin
GuiApi.Echo(Format('Stopping %s …',[dllName]));
//////////////////
// Don`t forget to
// Clear all data:
//////////////////
…
… Освобождение данных TDaqDataSheet
…
//////////////////
// Free DataSheet:
//////////////////
DaqDataSheet(0);//
//////////////////
GuiApi.Echo('Ok');
end;
////////////////////
// Main polling loop
////////////////////
DAQ_CMD_POLL: begin
/////////////////////////////
// USER data processing code:
/////////////////////////////
…
… Цикл сбора и обработки данных TDaqDataSheet
…
/////////////////////////////
// USER data processing done.
/////////////////////////////
end;
end; // case
end; // with
except
on E:Exception do begin
Echo(PluginName+RusEng(': ОШИБКА!',': ERROR!'));
if UsesBlaster then Voice('EXCEPTION');
Echo(E.Message);
Result:=-1;
end;
end;
end;Для выполнения полезной работы по сбору и обработке данных используются интерфейсы ICrwApi, ISysApi, IGuiApi, IDaqApi, содержащие большой набор функций для доступа к данным пакета. Например, для доступа к последней точке (x,y) кривой, подключенной к аналоговому входу (analog input) используются функции getai_xn(i), getai_yn(i), где i - номер аналогового входа.
Как правило, назначение функций и их аргументов понятно из названий. Многие функции интерфейсов ICrwApi, ISysApi, IDaqApi совпадают или имеют аналоги
Полный список и описание интерфейсов, классов, функций, переменных, констант модуля
_crw_crwapiс описанием интерфейса ICrwApi подключения плагинов см. тут или там.
В конце, после завершения функции плагина, необходимо экспортировать её:
/////////////////////////////////////////////////////////
{$I _crw_plugin_exports.inc} // Exports CRWDAQ_PLUGIN. //
/////////////////////////////////////////////////////////
// exports CRWDAQ_PLUGIN name CRWDAQ_PLUGIN_ID; //
/////////////////////////////////////////////////////////
begin
end.Экспорт выполняется вставкой {$I _crw_plugin_exports.inc}, что обеспечивает централизованное управление кодом плагинов.
Пакет содержит библиотеку образцов плагинов сбора данных daq, созданных по одному шаблону. Средства клонирования (копирования и сохранения под другим именем) позволяют создавать новые плагины, взяв эти образцы плагинов в качестве шаблона.
Шаблоны уже содержат необходимую структуру для работы плагинов сбора данных. Прикладному программисту нужно дополнить шаблон своим кодом, решающим требуемую задачу. Большинство потребностей прикладного программирования закрывает интерфейс ICrwApi, в состав которого входит еще ряд предметных интерфейсов:
Полный список и описание интерфейсов, классов, функций, переменных, констант модуля
_crw_crwapiс описанием интерфейса ICrwApi подключения плагинов см. тут или там.
Используйте шаблон hello_world.lpr.
А также модули библиотеки crwlib.
Полный список и описание интерфейсов, классов, функций, переменных, констант библиотеки
crwlibсм. тут или там.
Используйте шаблон daq_user_task.lpr.
А также модули библиотеки crwlib.
Полный список и описание интерфейсов, классов, функций, переменных, констант библиотеки
crwlibсм. тут или там.