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

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

  // Подвижный блок, передача через динамические переменные
  #include <windows.h>
  #include <math.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;
  }
  //========= Конец главной функции =========

  //=========== Блок управления =============
  // Структура личной области данных блока
  typedef struct
  { // Указатель на структуру подписки на скорость
     VLink;
    // Указатель на структуру подписки на направление
     ALink;
  } TestBlkMoveSetterData;

  // Модель блока управления
  extern "C" __declspec(dllexport)
    int  TestBlkMoveSetter(int CallMode,
                                   BlockData,
                                   ExtParam)
  {
  // 
  #define pStart  ((char *)(BlockData->VarTreeData))
  #define Start (*((char *)(pStart)))
  #define Ready (*((char *)(pStart+RDS_VSZ_S)))
  #define Speed (*((double *)(pStart+2*RDS_VSZ_S)))
  #define Angle (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_D)))
    // Вспомогательная переменная – указатель на личную область
    // данных блока, приведенный к правильному типу
    TestBlkMoveSetterData *privdata;

    switch(CallMode)
      { // Инициализация блока
        case :
          // Отведение памяти под личную область данных
          privdata=(TestBlkMoveSetterData*)
                    malloc(sizeof(TestBlkMoveSetterData));
          BlockData->BlockData=privdata;
          // Создание переменной для передачи скорости
          privdata->VLink=(
                            ,     // В родительской
                            "BlkMove_Speed",  // Имя переменной
                            "D",              // Тип double
                            TRUE,             // Запрет удаления
                            NULL);            // Без нач.значения
          // Создание переменной для передачи направления
          privdata->ALink=(
                            ,
                            "BlkMove_Angle",
                            "D",
                            TRUE,
                            NULL);
          break;

        // Очистка данных блока
        case :
          // Приведение указателя на личную область данных к
          // правильному типу
          privdata=(TestBlkMoveSetterData*)(BlockData->BlockData);
          // Удаление динамических переменных
          (privdata->VLink);
          (privdata->ALink);
          // Освобождение отведенной памяти
          free(privdata);
          break;

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

        // Выполнение такта моделирования
        case :
          // Приведение указателя на личную область данных к
          // правильному типу
          privdata=(TestBlkMoveSetterData*)(BlockData->BlockData);
          // Проверка существования переменной направления
          if(privdata->ALink!=NULL && privdata->ALink->Data!=NULL)
            { // Переменная существует – привести к типу double*
              double *pa=(double*)privdata->ALink->Data;
              if(*pa!=Angle) // Значение направления изменилось
                { // Записать значение в динамическую переменную
                  *pa=Angle;
                  // Уведомить всех подписчиков об изменении
                  (privdata->ALink);
                }
            }
          // Проверка существования переменной скорости
          if(privdata->VLink!=NULL && privdata->VLink->Data!=NULL)
            { // Переменная существует – привести к типу double*
              double *pv=(double*)privdata->VLink->Data;
              if(*pv!=Speed)
                { // Записать значение в динамическую переменную
                  *pv=Speed;
                  // Уведомить всех подписчиков об изменении
                  (privdata->VLink);
                }
            }
          break;
      }
    return ;
  // Отмена макроопределений
  #undef Angle
  #undef Speed
  #undef Ready
  #undef Start
  #undef pStart
  }
  //=========================================

  //============ Подвижный блок =============
  // Структура личной области данных блока
  typedef struct
  { // Указатель на структуру подписки на скорость
     VLink;
    // Указатель на структуру подписки на направление
     ALink;
    // Указатель на структуру подписки на время
     Time;

    // Дополнительные поля для хранения значений синуса
    // и косинуса направления движения блока
    double SinA;
    double CosA;
  } TestBlkMoveObjectData;

  // Модель перемещающегося блока
  extern "C" __declspec(dllexport)
    int  TestBlkMoveObject(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 y (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_D)))
  #define a (*((double *)(pStart+2*RDS_VSZ_S+2*RDS_VSZ_D)))
  #define t0 (*((double *)(pStart+2*RDS_VSZ_S+3*RDS_VSZ_D)))
    // Вспомогательная переменная – указатель на личную область
    // данных блока, приведенный к правильному типу
    TestBlkMoveObjectData *privdata;
    // Вспомогательные переменные для скорости и времени
    double v,time;

    switch(CallMode)
      { // Инициализация блока
        case :
          // Отведение памяти под личную область данных
          privdata=(TestBlkMoveObjectData*)
                    malloc(sizeof(TestBlkMoveObjectData));
          BlockData->BlockData=privdata;
          // Подписка на переменную скорости
          privdata->VLink=(
                          ,    // В родительской
                          "BlkMove_Speed", // Имя переменной
                          "D",             // Тип double
                          FALSE);          // Без поиска
          // Подписка на переменную направления
          privdata->ALink=(
                          ,
                          "BlkMove_Angle",
                          "D",
                          FALSE);
          // Подписка на переменную времени
          privdata->Time=(
                          ,  // В родительской
                          "DynTime",     // Имя переменной
                          "D",           // Тип double
                          TRUE);         // Поиск в иерархии
          break;

        // Очистка данных блока
        case :
          // Приведение указателя на личную область данных к
          // правильному типу
          privdata=(TestBlkMoveObjectData*)(BlockData->BlockData);
          // Прекращение подписки на все динамические переменные
          (privdata->VLink);
          (privdata->ALink);
          (privdata->Time);
          // Освобождение отведенной памяти
          free(privdata);
          break;

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

        // Реакция на изменение динамической переменной
        case :
          // Приведение указателя на личную область данных к
          // правильному типу
          privdata=(TestBlkMoveObjectData*)(BlockData->BlockData);
          // Проверка – удалось ли подписаться на все переменные
          // (если хотя бы один указатель – NULL, значит, не удалось)
          if(privdata->VLink==NULL ||  // Скорость
             privdata->ALink==NULL ||  // Направление
             privdata->Time==NULL)     // Время
            break;
          // Проверка – существуют ли все переменные
          // (если хотя бы один указатель – NULL, значит, не удалось)
          if(privdata->VLink->Data==NULL ||  // Скорость
             privdata->ALink->Data==NULL ||  // Направление
             privdata->Time->Data==NULL)     // Время
            break;
          // Если изменилась переменная направления, нужно вычислить
          // и запомнить новые значения ыинуса и косинуса угла
          if(ExtParam==(void*)(privdata->ALink))
            { // Изменилось направление – привести к типу double*
              double *pa=(double*)privdata->ALink->Data;
              // Значение угла в радианах
              a=(*pa)*M_PI/180.0;
              // Значения синуса и косинуса
              privdata->SinA=sin(a);
              privdata->CosA=cos(a);
            }
          // Записать во вспомогательные переменные v и time значения
          // скорости и времени
          v=*(double*)privdata->VLink->Data;
          time=*(double*)privdata->Time->Data;
          // Вычислить новое смещение изображения блока
          x+=v*(time-t0)*privdata->CosA;
          y-=v*(time-t0)*privdata->SinA;
          // Запомнить значение времени, для которого вычислены
          // новые координаты
          t0=time;
          break;
      }
    return ;
  // Отмена макроопределений
  #undef t0
  #undef a
  #undef y
  #undef x
  #undef Ready
  #undef Start
  #undef pStart
  }
  //=========================================


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