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