Полный исходный текст на языке 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 } //=========================================