Текущий раздел:

Описания RDS

Руководство программиста

Глава 2. Создание моделей блоков

§2.5. Статические переменные блоков

§2.5.8. Использование выходов с управляющими переменными

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

- TestSW2 – блок, передающий входное значение либо только по одной из двух выходных связей, либо по обеим;
- TestSW – блок-демультиплексор с выходом-массивом.

      // Управление срабатыванием выходных связей
      #include <windows.h>
      #include <RdsDef.h>
      // Подготовка описаний сервисных функций
      #define RDS_SERV_FUNC_BODY GetInterfaceFunctions
      #include <RdsFunc.h>

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

      //============ Переключатель ==============
      extern "C" __declspec(dllexport)
        int RDSCALL TestSW2(int CallMode,
                            RDS_PBLOCKDATA BlockData,
                            LPVOID 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 N (*((RDSINT32 *)(pStart+2*RDS_VSZ_S+RDS_VSZ_D)))
      #define L0 (*((char *)(pStart+2*RDS_VSZ_S+RDS_VSZ_D+RDS_VSZ_I)))
      #define L1 (*((char *)(pStart+2*RDS_VSZ_S+RDS_VSZ_D+RDS_VSZ_I+ \
                 RDS_VSZ_L)))
      #define y0 (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_D+RDS_VSZ_I+ \
                 2*RDS_VSZ_L)))
      #define y1 (*((double *)(pStart+2*RDS_VSZ_S+2*RDS_VSZ_D+ \
                 RDS_VSZ_I+2*RDS_VSZ_L)))
        switch(CallMode)
          { // Проверка типа переменных
            case RDS_BFM_VARCHECK:
              if(strcmp((char*)ExtParam,"{SSDILLDD}")==0)
                return RDS_BFR_DONE;
              return RDS_BFR_BADVARSMSG;

            // Выполнение такта моделирования
            case RDS_BFM_MODEL:
              switch(N)
                { case 0: // Передать данные на выход y0
                    y0=x;
                    L0=1; // Разрешить y0
                    L1=0; // Запретить y1
                    break;
                  case 1: // Передать данные на выход y1
                    y1=x;
                    L0=0; // Запретить y0
                    L1=1; // Разрешить y1
                    break;
                  default: // Передать данные на оба выхода
                    y0=y1=x;
                    L0=L1=1; // Разрешить оба выхода
                }
              break;
          }
        return RDS_BFR_DONE;
      // Отмена макроопределений
      #undef y1
      #undef y0
      #undef L1
      #undef L0
      #undef N
      #undef x
      #undef Ready
      #undef Start
      #undef pStart
      }
      //=========================================

      //=========== Демультиплексор =============
      extern "C" __declspec(dllexport)
        int RDSCALL TestSW(int CallMode,
                           RDS_PBLOCKDATA BlockData,
                           LPVOID 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 N (*((RDSINT32 *)(pStart+2*RDS_VSZ_S+RDS_VSZ_D)))
      #define pY ((void **)(pStart+2*RDS_VSZ_S+RDS_VSZ_D+RDS_VSZ_I))
        switch(CallMode)
          { // Проверка типа переменных
            case RDS_BFM_VARCHECK:
              if(strcmp((char*)ExtParam,"{SSDIMD}")==0)
                return RDS_BFR_DONE;
              return RDS_BFR_BADVARSMSG;

            // Выполнение такта моделирования
            case RDS_BFM_MODEL:
              if(N<0) // Значение N не должно быть отрицательным
                Ready=0; // Не передавать ничего по связям
              else // Значение N не отрицательно
                { int count;
                  double *array;
                  // Число элементов в массиве Y
                  count=RDS_ARRAYEXISTS(pY)?RDS_ARRAYCOLS(pY):0;
                  if(N>=count) // Число элементов недостаточно
                    { // Увеличение размера Y
                      if(!rdsResizeVarArray(pY,1,N+1,TRUE,NULL))
                        { // Ошибка: не удалось увеличить размер массива
                          rdsStopCalc(); // Остановка расчета
                          // Не передавать ничего по связям
                          Ready=0;
                          // Вывод сообщения
                          rdsMessageBoxW(L"Мало памяти",
                                         L"Ошибка",
                                         MB_OK | MB_ICONERROR);
                          return RDS_BFR_DONE;
                        }
                    }
                  // Получить указатель на первый элемент Y
                  array=(double*)RDS_ARRAYDATA(pY);
                  // Записать в Y[N] значение входа
                  array[N]=x;
                } // else (N>=0)
              break;
          }
        return RDS_BFR_DONE;
      // Отмена макроопределений
      #undef pY
      #undef N
      #undef x
      #undef Ready
      #undef Start
      #undef pStart
      }
      //=========================================