Навигация:
<< >> Оглавление Указатель
Текст С++

Полный исходный текст на языке C++ для библиотеки (DLL) с моделями блоков, иллюстрирующих отдельный расчет подсистемы. Библиотека содержит три модели:

  // Отдельный расчет подсистемы
  #include <windows.h>
  #include <RdsDef.h>
  // Подготовка описаний сервисных функций
  
  #include <RdsFunc.h>

  //==========  ==========
  int WINAPI ( /*hinst*/,
                           unsigned long reason,
                           void* /*lpReserved*/)
  { if(reason==DLL_PROCESS_ATTACH) // Загрузка DLL
      { // Получение доступа к функциям RDS
        if(!GetInterfaceFunctions())
           // Сообщение: старая версия RDS
      }
    return 1;
  }
  //========= Конец главной функции =========


  //=========================================
  // Включение/выключение отдельного расчета
  //=========================================
  extern "C" __declspec(dllexport)
    int  SetExclusiveCalc(int CallMode,
           BlockData,
           ExtParam)
  { // 
  #define pStart ((char *)(BlockData->VarTreeData))
  #define Start (*((char *)(pStart)))
  #define Ready (*((char *)(pStart+RDS_VSZ_S)))
  #define Lock (*((char *)(pStart+2*RDS_VSZ_S)))
  #define Unlock (*((char *)(pStart+3*RDS_VSZ_S)))
  #define Locked (*((char *)(pStart+4*RDS_VSZ_S)))
    switch(CallMode)
      { // Проверка типов переменных
        case :
          return strcmp((char*)ExtParam,"{SSSSL}")?
              :;

        // Такт расчета
        case :
          if(Lock) // Поступил сигнал включения отдельного расчета
            { if(Locked) // Отдельный расчет уже включен
                { Lock=0; // Сбрасываем сигнал, завершаем модель
                  break;
                }
              // Включаем отдельный расчет родительской подсистемы
              if((BlockData->Parent,TRUE))
                { // Включить удалось
                  Lock=0;   // Сбрасываем сигнал
                  Locked=1; // Запоминаем факт включения
                }
            }
          if(Unlock) // Поступил сигнал выключения
            { if(Locked) // Отдельный расчет был включен - выключаем
                (BlockData->Parent,FALSE);
              Locked=Lock=Unlock=0; // Сбрасываем сигналы и состояние
            }
          break;
      }
    return ;
  // Отмена макроопределений
  #undef Locked
  #undef Unlock
  #undef Lock
  #undef Ready
  #undef Start
  #undef pStart
  }
  //=========================================

  //=========================================
  // Счетчик тактов
  //=========================================
  extern "C" __declspec(dllexport)
      int  ChgCalcTickCount(int CallMode,
                           BlockData,
                           ExtParam)
  {
  // 
  #define pStart  ((char *)(BlockData->VarTreeData))
  #define Start (*((char *)(pStart)))
  #define Ready (*((char *)(pStart+RDS_VSZ_S)))
  #define Count (*((RDSINT32 *)(pStart+2*RDS_VSZ_S)))
  #define Stop (*((RDSINT32 *)(pStart+2*RDS_VSZ_S+RDS_VSZ_I)))
  #define Enabled (*((char *)(pStart+2*RDS_VSZ_S+2*RDS_VSZ_I)))
  #define x (*((double *)(pStart+2*RDS_VSZ_S+2*RDS_VSZ_I+RDS_VSZ_L)))
  #define xold (*((double *)(pStart+2*RDS_VSZ_S+2*RDS_VSZ_I+RDS_VSZ_L+RDS_VSZ_D)))
    switch(CallMode)
      { // Проверка типов переменных
        case :
          return strcmp((char*)ExtParam,"{SSIILDD}")?
            :;

        // Запуск расчета
        case :
          Start=1; // Принудительный запуск модели в следующем такте
          break;

        // Один такт моделирования
        case :
          if(!Enabled) // Работа блока не разрешена
            { xold=x; // Запоминаем значение входа
              break;
            }
          // Работа блока разрешена
          if(xold==x && Count==0)
            break; // Вход не изменился или счет не идет
          // Изменился вход (x!=xold) или уже считаем (Count!=0)
          Count++; // Увеличиваем число тактов
          if(Count>Stop) // Пора остановить расчет
            ();
          Start=1; // Принудительный перезапуск модели
          break;
      }
    return ;
  // Отмена макроопределений
  #undef xold
  #undef x
  #undef Enabled
  #undef Stop
  #undef Count
  #undef Ready
  #undef Start
  #undef pStart
  }
  //=========================================


  //=========================================================================
  // Блок y=Kx+C из прошлых примеров (нужен только как пример алгебраического
  // блока, в его модель после §2.7.4 не внесено никаких изменений)
  //=========================================================================
  // Проверка наличия связи у входа блока
   CheckBlockInputConnection(
     Block,            // Идентификатор блока
    int num,                      // Номер входа
     pVarDescr)// Указатель на структуру
                                  // описания переменной
  {  c; // Идентификатор связи
     PtDescr; // Структура описания точки связи

    // Заполнение служебных полей структур их размерами
    PtDescr.servSize=sizeof(PtDescr);
    pVarDescr->servSize=sizeof();

    // Получение описания переменной блока по номеру
    if((Block,num,pVarDescr)==NULL)
      return FALSE; // Нет такой переменной

    // Перебор всех связей, подключенных к этому блоку
    c=NULL;
    for(;;)
      { // Найти связь, следующую за c, и заполнить структуру
        // описания точки соединения PtDescr
        c=(Block,c,TRUE,FALSE,&PtDescr);
        if(c==NULL) // Больше нет связей
          break;
        // Найдена очередная связь – сравнение имени заданной
        // переменной с именем переменной точки этой связи
        if(strcmp(PtDescr.VarName,pVarDescr->Name)==0)
          return TRUE; // Имена совпали – есть связь, соединенная
                       // с переменной блока
      }
    // Все подключенные связи перебраны, а связь, подключенная
    // к заданной переменной так и не была найдена
    return FALSE;
  }
  //=========================================

  // Добавление поля для ввода или индикации вещественного параметра
  // 
  // 
  // 
   AddWinEditOrDisplayDouble(
     window, // Идентификатор объекта-окна
     Block,  // Блок
    int varnum,         // Номер переменной в блоке
    int ctrlnum,        // Идентификатор поля ввода в окне
    char *title)        // Заголовок поля или NULL
  { // Структура описания переменной блока
     VarDescr;
    // Проверка наличия связи у переменной varnum в блоке Block
    // и заполнение структуры VarDescr описанием переменной
    BOOL conn=CheckBlockInputConnection(Block,varnum,&VarDescr);

    if(conn) // К переменной подключена связь
      { // Вспомогательные переменные
        char *caption; // Заголовок поля
        double *cur; // Указатель на данные переменной
        // Заголовок поля формируется из имени переменной и
        // текста “подключена связь"
        caption=(title?title:VarDescr.Name,
                             " (подключена связь)",
                             FALSE);
        // Добавление поля для индикации текущего значения
        (window,0,ctrlnum,,
                       caption,80);
        // Освобождение динамически сформированной строки заголовка поля
        (caption);
        // Получение указателя на данные переменной
        cur=(double*)(Block,varnum,NULL);
        // Проверка – переменная должна существовать и иметь тип double
        if(cur!=NULL && VarDescr.Type=='D')
          // Занесение текущего значения переменной в поле
          (window,ctrlnum,,
                             *cur);
      }
    else // К переменной не подключена связь
      { // Вспомогательная переменная для значения по умолчанию
        char *defval;
        // Получение строки со значением переменной по умолчанию
        // (необходимо потом освободить при помощи rdsFree)
        defval=(Block,varnum,NULL);
        // Добавление поля для ввода параметра
        (window,0,ctrlnum,,
                       title?title:VarDescr.Name,80);
        // Занесение в поле ввода значения перменной по умолчанию
        (window,ctrlnum,,defval);
        // Освобождение динамически сформированной строки
        (defval);
      }
    // Возврат: TRUE – есть связь, FALSE – нет связи
    return conn;
  }
  //=========================================


  // Функция настройки K и C для модели блока y=Kx+C
  // 
  // 
  // 
   TestKxCSetup(
     Block, // Идентификатор блока
    int numK,          // Номер переменной K в блоке
    int numC)          // Номер переменной C в блоке
  {  window; // Идентификатор вспомогательного объекта
     ok;            // Пользователь нажал "OK"
     K_conn,C_conn; // Флаги наличия связей у K и C

    // Создание окна
    window=(FALSE,-1,-1,"Kx+C");

    // Добавление полей для ввода или индикации K и C
    // (в зависимости от наличия связей)
    K_conn=AddWinEditOrDisplayDouble(window,Block,numK,1,NULL);
    C_conn=AddWinEditOrDisplayDouble(window,Block,numC,2,NULL);

    // Открытие окна
    ok=(window,NULL);
    if(ok)
      { // Нажата кнопка OK – запись параметров в блок
        if(!K_conn) // У K нет связи
          { // Получение строки из поля ввода
            char *str=(window,1,);
            // Установка значения переменной K по умолчанию
            (Block,numK,str);
          }
        if(!C_conn) // У С нет связи
          { // Получение строки из поля ввода
            char *str=(window,2,);
            // Установка значения переменной C по умолчанию
            (Block,numC,str);
          }
      }
    // Уничтожение окна
    (window);
    // Возвращаемое значение – истина, если нажата "OK"
    return ok;
  }
  //=========================================

  // Функция модели блока
  extern "C" __declspec(dllexport)
    int  TestKxC(int CallMode,
                         BlockData,
                         ExtParam)
  {
  // 
  #define pStart ((char *)(BlockData->VarTreeData))
  #define Start (*((char *)(pStart)))
  #define Ready (*((char *)(pStart+RDS_VSZ_S)))
  #define x (*((double *)(pStart+2*RDS_VSZ_S)))
  #define K (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_D)))
  #define C (*((double *)(pStart+2*RDS_VSZ_S+2*RDS_VSZ_D)))
  #define y (*((double *)(pStart+2*RDS_VSZ_S+3*RDS_VSZ_D)))
    switch(CallMode)
      { // Проверка типа переменных
        case :
          if(strcmp((char*)ExtParam,"{SSDDDD}")==0)
            return ;
          return ;

        // Запуск расчета
        case :
          // Если это запуск с начала, взвести Start
          if((()ExtParam)->FirstStart)
            Start=1; // Модель запустится в первом же такте
          break;

        // Такт расчета
        case :
          y=K*x+C;
          break;

        // Функция настройки
        case :
          if(TestKxCSetup(BlockData->Block,3,4))
            { // Нажата “OK"
              Start=1; // Запустить модель в следующем такте
              return ;
            }
      }
    return ;
  // Отмена макроопределений
  #undef y
  #undef C
  #undef K
  #undef x
  #undef Ready
  #undef Start
  #undef pStart
  }
  //=========================================


<< >> Оглавление Указатель