Приложения
Приложение А. Функции, константы и структуры RDS
А.2. События блока и связанные с ними описания
А.2.4. События общего назначения
А.2.4.8. RDS_BFM_FUNCTIONCALL – вызов функции блока
Поток, в котором вызывается функция модели
Главный поток RDS или поток расчета (вызов выполняется в одном потоке с моделью вызывающего функцию блока).
Первый параметр функции модели (int CallMode)
Константа RDS_BFM_FUNCTIONCALL.
Третий параметр функции модели (void *ExtParam)
Указатель на структуру RDS_FUNCTIONCALLDATA, в которой содержатся идентификатор вызванной функции, ее параметры, а также другая информация, связанная с вызовом.
Возвращаемое функцией модели значение
Возвращенное значение передается вызвавшему функцию блоку, если функция вызвана непосредственно. При отложенном вызове возвращенное значение игнорируется.
Примечания
Вызов функций позволяет блокам передавать друг другу информацию непосредственно, без участия связей или динамических переменных (этот механизм подробно рассмотрен в §2.13 руководства программиста). Функция блока может вызываться как немедленно (выполнение функции модели вызвавшего блока приостанавливается до завершения вызванной функции), так и отложенным вызовом (выполнение функции модели вызвавшего блока продолжается, а после ее завершения вызывается модель другого блока). При вызове функции какого-либо блока его модель реагирует на событие RDS_BFM_FUNCTIONCALL, при этом в третьем параметре функции модели передается указатель на структуру RDS_FUNCTIONCALLDATA:
typedef struct { RDSINT32 Function; // Идентификатор функции LPVOID Data; // Параметры функции RDS_BHANDLE Caller; // Вызвавший блок BOOL Broadcast; // Вызов не одного блока, а нескольких RDSINT32 BroadcastCnt; // Номер блока среди всех вызванных BOOL Stop; // Прекратить вызов блоков BOOL Delayed; // Отложенный вызов DWORD DataBufSize; // Размер буфера при отложенном вызове } RDS_FUNCTIONCALLDATA; typedef RDS_FUNCTIONCALLDATA *RDS_PFUNCTIONCALLDATA;
Поля структуры
- Function (RDSINT32)
- Уникальный целый идентификатор вызванной функции. Прежде чем функцию блока можно будет вызывать или реагировать на ее вызов, имя этой функции необходимо зарегистрировать вызовом rdsRegisterFunction, который даст функции уникальный целый идентификатор. Именно он используется во всех сервисных функциях RDS, и с ним модель блока должна сравнить поле Function, чтобы определить, какая именно функция вызвана.
- Data (LPVOID)
- Указатель (LPVOID) на область памяти, в которой находятся параметры вызванной функции. Обычно эту область оформляют в виде структуры или массива. При немедленном (прямом) вызове функции вызванная модель может не только получать какие-либо параметры через эту область памяти, но и возвращать через нее значения, поскольку функция модели вызвавшего блока получит управление обратно только после завершения модели вызванного, и сможет считать данные из этой области памяти. При отложенном вызове функция вызвавшего блока завершится до самого вызова, поэтому в поле Data в этом случае передается указатель на созданную RDS копию области памяти, хранящей параметры функции – модель вызвавшего блока уже не сможет ничего оттуда считать.
- Caller (RDS_BHANDLE)
- Идентификатор (RDS_BHANDLE) вызвавшего функцию блока. Модель вызванного блока может использовать его для того чтобы, в свою очередь, вызвать у него какую-либо функцию в ответ.
- Broadcast (BOOL)
- Значение TRUE в этом поле сигнализирует о том, что данная функция была вызвана сразу у нескольких блоков, значение FALSE – что она вызвана только у данного блока.
- BroadcastCnt (RDSINT32)
- При Broadcast==TRUE в этом поле будет находиться порядковый (начинающийся с нуля) номер данного блока среди всех вызванных. Например, если функция вызвана у всех блоков какой-либо подсистемы, и в этой подсистеме находится три блока, при вызове первого из них в BroadcastCnt будет передан ноль, при вызове второго – 1, при вызове третьего – 2.
- Stop (BOOL)
- Исходно в этом поле записано значение FALSE. При Broadcast==TRUE модель вызванного блока может записать в Stop значение TRUE, запретив тем самым вызов функции для оставшихся блоков. Таким образом можно организовать, например, поиск в подсистеме блока, выполняющего какие-либо действия: можно вызвать функцию у всех блоков подсистемы и написать реакцию на вызов этой функции так, чтобы первый же выполняющий ее блок произвел необходимые действия или сообщил вызвавшему блоку свой идентификатор, а затем прервал дальнейший перебор блоков и вызов их функций, присвоив Stop значение TRUE.
- Delayed (BOOL)
- Значение FALSE в этом поле указывает на прямой вызов функции, значение TRUE – на отложенный.
- DataBufSize (DWORD)
- При отложенном вызове функции в этом поле передается размер области данных, указатель на которую находится в поле Data. Этот размер всегда известен, поскольку размер области данных с параметрами функции передается в сервисные функции, выполняющие отложенный вызов, вместе с указателем на ее начало. RDS делает копию этой области, чтобы после завершения модели вызвавшего функцию блока можно было передать эти данные вызванному.
Пример
Типичный пример непосредственного вызова функции какого-либо блока. Параметры функции передаются в структуре, в которой предусмотрено поле для проверки размера. Описание этой структуры должно быть доступно и вызывающей функции модели (для вызова), и вызываемой (для реакции).
// Структура параметров функции typedef struct { DWORD servSize; // Размер этой структуры int IParam; // Целый параметр double DParam; // Вещественный параметр } TMyFuncParam; ... // Глобальная переменная для идентификатора функции int MyFuncId; ... // Регистрация функции блока (например, в главной функции DLL) MyFuncId=rdsRegisterFunction("MyFunctionName");
Вызов функции блока:
RDS_BHANDLE block=…; // Идентификатор вызываемого блока TMyFuncParam param; // Структура параметров функции int retvalue; // Результат возврата функции param.servSize=sizeof(param); param.IParam=100; param.DParam=3.14; // Вызов функции retval=rdsCallBlockFunction(block,MyFuncId,¶m);
Реакция на вызов функции в модели блока:
TMyFuncParam *pparam; // Структура параметров функции RDS_PFUNCTIONCALLDATA pfuncdata; // Данные вызова switch(CallMode) { case RDS_BFM_FUNCTIONCALL: pfuncdata=(RDS_PFUNCTIONCALLDATA)ExtParam; if(pfuncdata->Function==MyFuncId) { pparam=(TMyFuncParam*)(pfuncdata->Data); if(pparam->servSize==sizeof(TMyFuncParam)) { // Выполнение функции … } } break; }
См. также
RDS_BFM_CHECKFUNCSUPPORT, rdsCheckBlockFunctionSupport, rdsCallBlockFunction, rdsQueueCallBlockFunction, rdsBroadcastFunctionCallsEx.