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

Описания RDS

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

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

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

§2.5.6. Работа с переменными произвольного типа

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

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

      // Переменные произвольного типа
      #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 TestVarSwitch(int CallMode,
                                  RDS_PBLOCKDATA BlockData,
                                  LPVOID ExtParam)
      {
      // Макроопределения для статических переменных
      #define pStart  ((char *)(BlockData->VarTreeData))
      #define Start (*((char *)(pStart)))
      #define Ready (*((char *)(pStart+RDS_VSZ_S)))
      #define px ((void **)(pStart+2*RDS_VSZ_S))
      #define Enable (*((char *)(pStart+2*RDS_VSZ_S+RDS_VSZ_V)))
      #define py ((void **)(pStart+2*RDS_VSZ_S+RDS_VSZ_V+RDS_VSZ_L))
        switch(CallMode)
          { // Проверка типа переменных
            case RDS_BFM_VARCHECK:
              if(strcmp((char*)ExtParam,"{SSVLV}")==0)
                return RDS_BFR_DONE;
              return RDS_BFR_BADVARSMSG;

            // Выполнение такта моделирования
            case RDS_BFM_MODEL:
              if(Enable) // Передача разрешена
                rdsCopyRuntimeType(py,px); // Копирование x в y
              else // Передача запрещена
                Ready=0; // Блокировка передачи данных по связям
              break;
          }
        return RDS_BFR_DONE;
      // Отмена макроопределений
      #undef py
      #undef Enable
      #undef px
      #undef Ready
      #undef Start
      #undef pStart
      }
      //=========================================

      //====== Определение типа переменной ======
      extern "C" __declspec(dllexport)
        int RDSCALL TestVar1(int CallMode,
                             RDS_PBLOCKDATA BlockData,
                             LPVOID ExtParam)
      {
      // Макроопределения для статических переменных
      #define pStart  ((char *)(BlockData->VarTreeData))
      #define Start (*((char *)(pStart)))
      #define Ready (*((char *)(pStart+RDS_VSZ_S)))
      #define px ((void **)(pStart+2*RDS_VSZ_S))
      #define type (*((char **)(pStart+2*RDS_VSZ_S+RDS_VSZ_V)))
      #define val (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_V+RDS_VSZ_A)))
        // Вспомогательные переменные
        char *s;  // Строка фактического типа входа x
        void *v;  // Указатель на данные входа x

        switch(CallMode)
          { // Проверка типа переменных
            case RDS_BFM_VARCHECK:
              if(strcmp((char*)ExtParam,"{SSVAD}")==0)
                return RDS_BFR_DONE;
              return RDS_BFR_BADVARSMSG;

            // Выполнение такта моделирования
            case RDS_BFM_MODEL:
              // Освобождение прежнего значения строки type
              rdsFree(type);
              // Получение указателя на данные (v)
              // и строки фактического типа (s) входа x
              v=rdsGetRuntimeTypeData(px,&s);
              // Занесение строки типа в выход type
              type=s;
              // Анализ типа, если переменная не пуста
              if(v!=NULL) // У входа x есть фактический тип
                switch(*s) // Анализ первого символа строки типа
                  { case 'D': // Фактический тип – double
                      val=*((double*)v);
                      break;
                    case 'I': // Фактический тип – int
                      val=*((int*)v);
                      break;
                    case 'M': // Фактический тип – матрица или массив
                      if(RDS_ARRAYEXISTS(v)) // Матрица не пуста
                        val=RDS_ARRAYROWS(v)*RDS_ARRAYCOLS(v);
                      else // Матрица пуста (0x0)
                        val=0;
                      break;
                    default: // Другой фактический тип
                      val=0.0;
                  } // Конец switch(*s)
              else // У входа x нет фактического типа
                val=0.0;
              break;
          }
        return RDS_BFR_DONE;
      // Отмена макроопределений
      #undef val
      #undef type
      #undef px
      #undef Ready
      #undef Start
      #undef pStart
      }
      //=========================================

      //==== Программное задание типа выхода ====
      extern "C" __declspec(dllexport)
        int RDSCALL TestVar2(int CallMode,
                             RDS_PBLOCKDATA BlockData,
                             LPVOID ExtParam)
      {
      // Макроопределения для статических переменных
      #define pStart  ((char *)(BlockData->VarTreeData))
      #define Start (*((char *)(pStart)))
      #define Ready (*((char *)(pStart+RDS_VSZ_S)))
      #define Type (*((RDSINT32 *)(pStart+2*RDS_VSZ_S)))
      #define py ((void **)(pStart+2*RDS_VSZ_S+RDS_VSZ_I))
        // Вспомогательные переменные
        int *i_ptr;    // Указатель на данные для целого типа
        double *d_ptr; // Указатель на данные для вещественного типа
        void *v_ptr;   // Указатель на данные для матрицы

        switch(CallMode)
          { // Проверка типа переменных
            case RDS_BFM_VARCHECK:
              if(strcmp((char*)ExtParam,"{SSIV}")==0)
                return RDS_BFR_DONE;
              return RDS_BFR_BADVARSMSG;

            // Выполнение такта моделирования
            case RDS_BFM_MODEL:
              switch(Type)
                { case 0: // Выдать целое число
                    // Установить целый тип выхода
                    i_ptr=(int*)rdsSetRuntimeType(py,"I");
                    // Присвоить выходу значение
                    if(i_ptr) *i_ptr=1;
                    break;
                  case 1: // Выдать вещественное число
                    // Установить вещественный тип выхода
                    d_ptr=(double*)rdsSetRuntimeType(py,"D");
                    // Присвоить выходу значение
                    if(d_ptr) *d_ptr=2.0;
                    break;
                  default: // Выдать матрицу
                    // Тип выхода – матрица double
                    v_ptr=rdsSetRuntimeType(py,"MD");
                    if(v_ptr)
                      { double *array;
                        // Установить размер матрицы
                        rdsResizeVarArray(v_ptr,2,2,FALSE,NULL);
                        // Получить указатель на первый элемент
                        array=(double*)RDS_ARRAYDATA(v_ptr);
                        // Заполнить матрицу числами 1,2,3,4
                        for(int i=0;i<4;i++)
                          array[i]=i+1;
                      }
                } // Конец switch(Type)
              break;

          }
        return RDS_BFR_DONE;
      // Отмена макроопределений
      #undef py
      #undef Type
      #undef Ready
      #undef Start
      #undef pStart
      }
      //=========================================