Полный исходный текст на языке C++ для библиотеки (DLL) с моделями блоков, работающих одновременно с несколькими динамическими переменными. Библиотека содержит две модели:
- TestBlkMoveSetter – блок, записывающий в динамические переменные значения скорости и угла поворота;
- TestBlkMoveObject – блок, перемещающийся в окне подсистемы со скоростью и в направлении, считанными из динамических переменных.
// Подвижный блок, передача через динамические переменные #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; } //========= Конец главной функции ========= //=========== Блок управления ============= // Структура личной области данных блока typedef struct { // Указатель на структуру подписки на скорость RDS_PDYNVARLINK VLink; // Указатель на структуру подписки на направление RDS_PDYNVARLINK ALink; } TestBlkMoveSetterData; // Модель блока управления extern "C" __declspec(dllexport) int RDSCALL TestBlkMoveSetter(int CallMode, RDS_PBLOCKDATA BlockData, LPVOID 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 RDS_BFM_INIT: // Отведение памяти под личную область данных privdata=(TestBlkMoveSetterData*) malloc(sizeof(TestBlkMoveSetterData)); BlockData->BlockData=privdata; // Создание переменной для передачи скорости privdata->VLink=rdsCreateAndSubscribeDV( RDS_DVPARENT, // В родительской "BlkMove_Speed", // Имя переменной "D", // Тип double TRUE, // Запрет удаления NULL); // Без нач.значения // Создание переменной для передачи направления privdata->ALink=rdsCreateAndSubscribeDV( RDS_DVPARENT, "BlkMove_Angle", "D", TRUE, NULL); break; // Очистка данных блока case RDS_BFM_CLEANUP: // Приведение указателя на личную область данных к // правильному типу privdata=(TestBlkMoveSetterData*)(BlockData->BlockData); // Удаление динамических переменных rdsDeleteDVByLink(privdata->VLink); rdsDeleteDVByLink(privdata->ALink); // Освобождение отведенной памяти free(privdata); break; // Проверка типа статических переменных case RDS_BFM_VARCHECK: if(strcmp((char*)ExtParam,"{SSDD}")==0) return RDS_BFR_DONE; return RDS_BFR_BADVARSMSG; // Выполнение такта моделирования case RDS_BFM_MODEL: // Приведение указателя на личную область данных к // правильному типу privdata=(TestBlkMoveSetterData*)(BlockData->BlockData); // Проверка существования переменной направления if(privdata->ALink!=NULL && privdata->ALink->Data!=NULL) { // Переменная существует – привести к типу double* double *pa=(double*)privdata->ALink->Data; if(*pa!=Angle) // Значение направления изменилось { // Записать значение в динамическую переменную *pa=Angle; // Уведомить всех подписчиков об изменении rdsNotifyDynVarSubscribers(privdata->ALink); } } // Проверка существования переменной скорости if(privdata->VLink!=NULL && privdata->VLink->Data!=NULL) { // Переменная существует – привести к типу double* double *pv=(double*)privdata->VLink->Data; if(*pv!=Speed) { // Записать значение в динамическую переменную *pv=Speed; // Уведомить всех подписчиков об изменении rdsNotifyDynVarSubscribers(privdata->VLink); } } break; } return RDS_BFR_DONE; // Отмена макроопределений #undef Angle #undef Speed #undef Ready #undef Start #undef pStart } //========================================= //============ Подвижный блок ============= // Структура личной области данных блока typedef struct { // Указатель на структуру подписки на скорость RDS_PDYNVARLINK VLink; // Указатель на структуру подписки на направление RDS_PDYNVARLINK ALink; // Указатель на структуру подписки на время RDS_PDYNVARLINK Time; // Дополнительные поля для хранения значений синуса // и косинуса направления движения блока double SinA; double CosA; } TestBlkMoveObjectData; // Модель перемещающегося блока extern "C" __declspec(dllexport) int RDSCALL TestBlkMoveObject(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 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 RDS_BFM_INIT: // Отведение памяти под личную область данных privdata=(TestBlkMoveObjectData*) malloc(sizeof(TestBlkMoveObjectData)); BlockData->BlockData=privdata; // Подписка на переменную скорости privdata->VLink=rdsSubscribeToDynamicVar( RDS_DVPARENT, // В родительской "BlkMove_Speed", // Имя переменной "D", // Тип double FALSE); // Без поиска // Подписка на переменную направления privdata->ALink=rdsSubscribeToDynamicVar( RDS_DVPARENT, "BlkMove_Angle", "D", FALSE); // Подписка на переменную времени privdata->Time=rdsSubscribeToDynamicVar( RDS_DVPARENT, // В родительской "DynTime", // Имя переменной "D", // Тип double TRUE); // Поиск в иерархии break; // Очистка данных блока case RDS_BFM_CLEANUP: // Приведение указателя на личную область данных к // правильному типу privdata=(TestBlkMoveObjectData*)(BlockData->BlockData); // Прекращение подписки на все динамические переменные rdsUnsubscribeFromDynamicVar(privdata->VLink); rdsUnsubscribeFromDynamicVar(privdata->ALink); rdsUnsubscribeFromDynamicVar(privdata->Time); // Освобождение отведенной памяти free(privdata); break; // Проверка типа статических переменных case RDS_BFM_VARCHECK: if(strcmp((char*)ExtParam,"{SSDDDD}")==0) return RDS_BFR_DONE; return RDS_BFR_BADVARSMSG; // Реакция на изменение динамической переменной case RDS_BFM_DYNVARCHANGE: // Приведение указателя на личную область данных к // правильному типу 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 RDS_BFR_DONE; // Отмена макроопределений #undef t0 #undef a #undef y #undef x #undef Ready #undef Start #undef pStart } //=========================================