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

Описания RDS

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

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

§2.6. Динамические переменные

§2.6.5. Работа со сложными динамическими переменными

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

- TestDynMatrCreate – блок-передатчик;
- TestDynMatrGet – блок-приемник.

      // Передача матрицы через динамическую переменную
      #include <windows.h>
      #include <math.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 TestDynMatrCreate(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))
        // Вспомогательная переменная – указатель на структуру подписки
        RDS_PDYNVARLINK Link;

        switch(CallMode)
          { // Инициализация блока
            case RDS_BFM_INIT:
              // Создание динамической переменной
              Link=rdsCreateAndSubscribeDV(RDS_DVROOT, // В корневой
                                           "DynMatr",  // Имя переменной
                                           "MD",       // Тип
                                           TRUE,       // Запрет удаления
                                           NULL);      // Без нач.знач.
              // Запомнить указатель на структуру подписки
              BlockData->BlockData=Link;
              break;

            // Очистка
            case RDS_BFM_CLEANUP:
              // Запомненный указатель на структуру подписки
              Link=(RDS_PDYNVARLINK)BlockData->BlockData;
              // Удалить переменную
              rdsDeleteDVByLink(Link);
              break;

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

            // Такт расчета
            case RDS_BFM_MODEL:
              // Запомненный указатель на структуру подписки
              Link=(RDS_PDYNVARLINK)BlockData->BlockData;
              // Если переменная существует, копировать входную матрицу
              // в матрицу динамической переменной
              if(Link!=NULL && Link->Data!=NULL)
                { // Копирование X в динамическую переменную
                  rdsCopyVarArray(Link->Data,pX);
                  // Уведомление подписчиков
                  rdsNotifyDynVarSubscribers(Link);
                }
              break;
          }

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

      //============ Блок-приемник ==============
      extern "C" __declspec(dllexport)
        int RDSCALL TestDynMatrGet(int CallMode,
                                   RDS_PBLOCKDATA BlockData,
                                   LPVOID ExtParam)
      {
      // Макроопределения для статических переменных
      #define pStart  ((char *)(BlockData->VarTreeData))
      #define Start (*((char *)(pStart)))
      #define Ready (*((char *)(pStart+RDS_VSZ_S)))
      #define pY ((void **)(pStart+2*RDS_VSZ_S))
      #define s (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_M)))
        // Вспомогательная переменная – указатель на структуру подписки
        RDS_PDYNVARLINK Link;

        switch(CallMode)
          { // Инициализация блока
            case RDS_BFM_INIT:
              // Подписка на динамическую переменную
              Link=rdsSubscribeToDynamicVar(RDS_DVROOT, // В корневой
                                           "DynMatr",   // Имя
                                           "MD",        // Тип
                                           FALSE);      // Без поиска
              // Запомнить указатель на структуру подписки
              BlockData->BlockData=Link;
              break;

            // Очистка
            case RDS_BFM_CLEANUP:
              // Запомненный указатель на структуру подписки
              Link=(RDS_PDYNVARLINK)BlockData->BlockData;
              // Прекратить подписку
              rdsUnsubscribeFromDynamicVar(Link);
              break;

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

            // Изменение динамической переменой или такт расчета
            case RDS_BFM_DYNVARCHANGE:
            case RDS_BFM_MODEL:
              // Запомненный указатель на структуру подписки
              Link=(RDS_PDYNVARLINK)BlockData->BlockData;
              // В s будут суммироваться элементы матрицы
              s=0;
              // Проверка существования динамической переменной
              if(Link!=NULL && Link->Data!=NULL)
                { // Копировать динамическую матрицу в Y
                  rdsCopyVarArray(pY,Link->Data);
                  // Если матрица не нулевого размера – суммировать
                  if(RDS_ARRAYEXISTS(Link->Data))
                    { // Число элементов в матрице
                      int count=RDS_ARRAYROWS(Link->Data)*
                                RDS_ARRAYCOLS(Link->Data);
                      // Указатель на начало данных матрицы
                      double *data=(double*)RDS_ARRAYDATA(Link->Data);
                      // Суммирование элементов в цикле
                      for(int i=0;i<count;i++)
                        s+=data[i];
                    }
                  // Взвести Ready для передачи выходов по связям
                  Ready=1;
                }
              break;
          }

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