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

Описания RDS

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

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

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

§2.5.3. Доступ к матрицам и массивам

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

- TestMatr – модель с использованием вспомогательных структур RDS_ARRAYACCESSDATA;
- TestMatr1 – модель с использованием макросов;
- TestMatr2 – модель с использованием макросов, все элементы матрицы обрабатываются в одном цикле.

Изменения от варианта к варианту выделены цветом.

      // Умножение матрицы на константу
      #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 TestMatr(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 k (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_M)))
      #define pY ((void **)(pStart+2*RDS_VSZ_S+RDS_VSZ_M+RDS_VSZ_D))
        // Структуры с информацией о матрицах
        RDS_ARRAYACCESSDATA XD,YD;
        switch(CallMode)
          { // Проверка типа переменных
            case RDS_BFM_VARCHECK:
              if(strcmp((char*)ExtParam,"{SSMDDMD}")==0)
                return RDS_BFR_DONE;
              return RDS_BFR_BADVARSMSG;

            // Выполнение такта моделирования
            case RDS_BFM_MODEL:
              // Считать информацию о матрице X в структуру XD
              rdsGetVarArrayAccessData(pX,&XD);
              if(XD.Exists) // Матрица X существует
                { // Задать размер Y и считать информацию о ней в YD
                  rdsResizeVarArray(pY,XD.Rows,XD.Cols,FALSE,&YD);
                  // Присвоить значения элементам Y
                  for(int r=0;r<XD.Rows;r++)
                    for(int c=0;c<XD.Cols;c++)
                      RDS_ARRAYITEM(double,&YD,r,c)=
                        k*RDS_ARRAYITEM(double,&XD,r,c);
                }
              else // Матрица X не существует
                // Очистить матрицу Y
                rdsResizeVarArray(pY,0,0,FALSE,NULL);
              break;
          }
        return RDS_BFR_DONE;
      // Отмена макроопределений
      #undef pY
      #undef k
      #undef pX
      #undef Ready
      #undef Start
      #undef pStart
      }
      //=========================================

      //===================================================
      // Второй вариант - доступ к матрицам через указатели
      //===================================================

      //============= Модель блока ==============
      extern "C" __declspec(dllexport)
        int RDSCALL TestMatr1(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 k (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_M)))
      #define pY ((void **)(pStart+2*RDS_VSZ_S+RDS_VSZ_M+RDS_VSZ_D))
        // Структуры с информацией о матрицах
        switch(CallMode)
          { // Проверка типа переменных
            case RDS_BFM_VARCHECK:
              if(strcmp((char*)ExtParam,"{SSMDDMD}")==0)
                return RDS_BFR_DONE;
              return RDS_BFR_BADVARSMSG;

            // Выполнение такта моделирования
            case RDS_BFM_MODEL:
              if(RDS_ARRAYEXISTS(pX)) // Матрица X существует
                { // Вспомогательные переменные
                  int xr,xc;
                  double *ydata,*xdata;
                  // Получить размеры матрицы X
                  xr=RDS_ARRAYROWS(pX);
                  xc=RDS_ARRAYCOLS(pX);
                  // Задать размер Y равным размеру X
                  rdsResizeVarArray(pY,xr,xc,FALSE,NULL);
                  // Получить указатель на первый элемент X
                  xdata=(double*)RDS_ARRAYDATA(pX);
                  // Получить указатель на первый элемент Y
                  ydata=(double*)RDS_ARRAYDATA(pY);
                  // Присвоить значения элементам Y
                  for(int r=0;r<xr;r++)
                    for(int c=0;c<xc;c++)
                      ydata[r*xc+c]=k*xdata[r*xc+c];
                }
              else // Матрица X пуста
                rdsResizeVarArray(pY,0,0,FALSE,NULL);
              break;
          }
        return RDS_BFR_DONE;
      // Отмена макроопределений
      #undef pY
      #undef k
      #undef pX
      #undef Ready
      #undef Start
      #undef pStart
      }
      //=========================================

      //=======================================
      // Третий вариант - один цикл вместо двух
      //=======================================

      //============= Модель блока ==============
      extern "C" __declspec(dllexport)
        int RDSCALL TestMatr2(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 k (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_M)))
      #define pY ((void **)(pStart+2*RDS_VSZ_S+RDS_VSZ_M+RDS_VSZ_D))
        // Структуры с информацией о матрицах
        switch(CallMode)
          { // Проверка типа переменных
            case RDS_BFM_VARCHECK:
              if(strcmp((char*)ExtParam,"{SSMDDMD}")==0)
                return RDS_BFR_DONE;
              return RDS_BFR_BADVARSMSG;

            // Выполнение такта моделирования
            case RDS_BFM_MODEL:
              if(RDS_ARRAYEXISTS(pX)) // Матрица X существует
                { // Вспомогательные переменные
                  int xr,xc;
                  double *ydata,*xdata;
                  // Получить размеры матрицы X
                  xr=RDS_ARRAYROWS(pX);
                  xc=RDS_ARRAYCOLS(pX);
                  // Задать размер Y равным размеру X
                  rdsResizeVarArray(pY,xr,xc,FALSE,NULL);
                  // Получить указатель на первый элемент X
                  xdata=(double*)RDS_ARRAYDATA(pX);
                  // Получить указатель на первый элемент Y
                  ydata=(double*)RDS_ARRAYDATA(pY);
                  // Присвоить значения элементам Y
                  for(int i=0;i<xr*xc;i++)
                    ydata[i]=k*xdata[i];
                }
              else // Матрица X пуста
                rdsResizeVarArray(pY,0,0,FALSE,NULL);
              break;
          }
        return RDS_BFR_DONE;
      // Отмена макроопределений
      #undef pY
      #undef k
      #undef pX
      #undef Ready
      #undef Start
      #undef pStart
      }
      //=========================================