Описание пользователя
Глава 3. Использование стандартных модулей автокомпиляции
§3.7. Краткий перечень вводимых в модель описаний и реакций на события
§3.7.5. Вызов функции блока
Описывается реакция на вызов функции блока, то есть на непосредственный вызов модели данного блока моделью другого.
Для каждой функции блока, добавленной в редактор модели (см. §3.5.5), модуль автокомпиляции автоматически добавляет в список событий реакцию на вызов этой функции. Текст этой реакции вводится на вкладке «» левой панели редактора модели: раздел «», подраздел с именем нужной функции (см. рис. 468). Написание реакций на вызовы функций подробно и с примерами рассматривается в §3.6.13, здесь же мы рассмотрим техническую сторону этих реакций.
В классе блока для реакции на вызов создается функция-член с именем, автоматически сформированным по имени объекта функции, которое пользователь ввел при ее добавлении в модель. В зависимости от того, есть ли у функции параметр, эта функция-член будет иметь два или три параметра. Если параметр у функции есть, созданная для реакции на ее вызов функция-член будет выглядеть так (цветом выделены части текста, зависящие от конкретной функции):
// Block function call reaction "имя_функции" void rdsbcppBlockClass::имя_реакции( тип_указателя_на_параметр Param, RDS_PFUNCTIONCALLDATA FData, int &Result) { … пользовательский текст реакции … }
В параметре Param находится указатель на параметр вызванной функции блока, переданный другой моделью в момент этого вызова. Параметром функции блока, если он есть, всегда должен быть какой-нибудь указатель, и тип этого указателя вводится при добавлении функции в модель (см. рис. 470, поле ввода «»). Если, например, в качестве параметра функции было введено «TMyFuncParam*» (то есть «указатель на некоторую структуру TMyFuncParam»), Param в реакции тоже будет иметь тип TMyFuncParam*.
Параметр FData – это указатель на общую для всех функций структуру описания события RDS_FUNCTIONCALLDATA, из полей которой можно узнать, как и кем именно вызвана функция:
typedef struct {
int Function; // Идентификатор функции в RDS
LPVOID Data; // Параметр функции
int Reserved; // Зарезервировано (не используется)
RDS_BHANDLE Caller; // Вызвавший блок
BOOL Broadcast; // Вызов не одного блока, а нескольких
int BroadcastCnt; // Номер блока среди всех вызванных
BOOL Stop; // Прекратить вызов блоков (возврат)
BOOL Delayed; // Отложенный вызов
DWORD DataBufSize; // Размер буфера при отложенном вызове
} RDS_FUNCTIONCALLDATA;
typedef RDS_FUNCTIONCALLDATA *RDS_PFUNCTIONCALLDATA;
Поля этой структуры имеют следующий смысл:
- Function (int)
- Уникальный целый идентификатор вызванной функции в RDS. Этот идентификатор присваивается функции автоматически. Его также можно в любой момент получить из объекта функции, создаваемого модулем автокомпиляции для работы с ней, при помощи функции-члена Id этого объекта.
- Data (LPVOID)
- Указатель, являющийся параметром функции (NULL, если параметра нет). Значение этого поля совпадает с описанным выше параметром Param, за исключением типа: Param уже приведен к нужному типу, а поле Data – универсальный указатель типа void*. В автокомпилируемых моделях использовать это поле не имеет смысла, вместо него используется Param.
- Caller (RDS_BHANDLE)
- Идентификатор вызвавшего функцию блока. Модель вызванного блока может использовать его для того чтобы, в свою очередь, вызвать у него какую-либо функцию в ответ.
- Broadcast (BOOL)
- Значение TRUE в этом поле сигнализирует о том, что данная функция была вызвана сразу у нескольких блоков (см. §3.6.13.2), значение FALSE – что она вызвана только у данного блока (см. §3.6.13.3).
- BroadcastCnt (BOOL)
- При Broadcast==TRUE в этом поле будет находиться порядковый (начинающийся с нуля) номер данного блока среди всех вызванных. Например, если функция вызвана у всех блоков какой-либо подсистемы, и в этой подсистеме находится три блока, при вызове первого из них в BroadcastCnt будет передан ноль, при вызове второго – 1, при вызове третьего – 2.
- Stop (BOOL)
- Флаг прекращения вызова функции у группы блоков. Исходно в этом поле записано значение FALSE. При Broadcast==TRUE модель вызванного блока может записать в Stop значение TRUE, запретив тем самым вызов функции для оставшихся блоков. Таким образом можно, например, организовать поиск в подсистеме блока, выполняющего какие-либо действия: можно вызвать функцию у всех блоков подсистемы и написать реакцию на вызов этой функции так, чтобы первый же выполняющий ее блок произвел необходимые действия или сообщил вызвавшему блоку свой идентификатор, а затем прервал дальнейший перебор блоков и вызов их функций, присвоив Stop значение TRUE.
- Delayed (BOOL)
- Значение FALSE в этом поле указывает на прямой вызов функции, значение TRUE – на отложенный. Отложенные вызовы не поддерживаются модулем автокомпиляции напрямую через объекты функций, но их можно выполнять при помощи обычных функций RDS (см. §2.13.5 руководства программиста).
- DataBufSize (DWORD)
- При отложенном вызове функции в этом поле передается размер области данных, указатель на которую находится в поле Data.
Третий параметр функции реакции – это ссылка на целую переменную Result. Значение этой переменной возвращается вызвавшему блоку. Допустим, например, что в модель какого-то блока добавлена некоторая функция без параметров, в реакции на вызов которой записано:
Result=123;
В модель другого блока добавлена та же самая функция, и объект для работы с ней назван MyFuncObject. Если идентификатор первого блока будет записан в переменной block (например, этот блок был найден по какому-то признаку перебором всех блоков подсистемы), то вызов
int i=MyFuncObject.Call(block);
запишет в переменную i значение 123. По умолчанию в Result записано значение 0 – если в реакции на вызов функции Result ничего не будет присвоено, этот ноль там и останется и будет возвращен вызвавшему блоку.
Если у функции нет параметра, в функции-члене для нее просто будет отсутствовать параметр Param:
// Block function call reaction "имя_функции" void rdsbcppBlockClass::имя_реакции( RDS_PFUNCTIONCALLDATA FData, int &Result) { … пользовательский текст реакции … }
Смысл оставшихся двух параметров остается тем же.
При написании моделей блоков без использования модуля автокомпиляции вызову любой функции блока соответствует константа RDS RDS_BFM_FUNCTIONCALL. При этом, чтобы понять, какая именно функция вызвана, программист должен сам анализировать значение поля Function в переданной в модель структуре RDS_FUNCTIONCALLDATA. Модуль автокомпиляции несколько упрощает работу, вставляя этот анализ в модель автоматически.