Полный исходный текст на языке C++ для библиотеки (DLL) с примером модуля автокомпиляции моделей блоков для языка C. Пример модуля пока реагирует только на инициализацию, выгрузку из памяти и настройку – собственно компиляция и редактирование моделей пока не реализовано.
#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; } //========= Конец главной функции ========= // Класс личной области данных модуля автокомпиляции class TCAutoCompData { private: // Пути char *CompPath; // к компилятору char *LinkPath; // к редактору связей (link) char *IncludePath; // к файлам заголовков char *LibPath; // к библиотекам // Нужно ли добавлять путь к exe-файлу компилятора и редактора связей BOOL CompSetPath,LinkSetPath; // Параметры командной строки char *CompParams; // компилятора char *LinkParams; // редактора связей // Параметры исходного текста char *DllMainName; // имя главной функции DLL char *ModelFuncHdr; // заголовок функции модели char *Exported; // экспортированное имя функции // Освободить все динамические строки void FreeAllStrings(void) { rdsFree(CompPath); rdsFree(LinkPath); rdsFree(IncludePath); rdsFree(LibPath); rdsFree(CompParams); rdsFree(LinkParams); rdsFree(DllMainName); rdsFree(ModelFuncHdr); rdsFree(Exported); }; public: // Чтение параметров модуля из INI-файла void ReadFromIni(const char *IniFileName); // Запись параметров модуля в INI-файл void WriteToIni(const char *IniFileName); // Настройка параметров модуля void Setup(const char *IniFileName); // Конструктор класса TCAutoCompData(void) { IncludePath=LibPath=NULL; CompSetPath=LinkSetPath=TRUE; #ifdef RDS_WIN64 CompPath=rdsDynStrCopy( "$RDS$\\mingw-w64\\bin\\g++.exe"); LinkPath=rdsDynStrCopy(CompPath); CompParams=rdsDynStrCopy( "-Wall -m64 -g -I\"$RDSINCLUDE$\" -c \"$TEMP$\\$NAME$.cpp\" -o \"$TEMP$\\$NAME$.o\"" ); LinkParams=rdsDynStrCopy( "-shared -static -static-libgcc -static-libstdc++ -Wl,--dll \"$TEMP$\\$NAME$.o\" -o \"$TEMP$\\$NAME$.dll\" -s -m64 -luser32" ); DllMainName=rdsDynStrCopy("extern \"C\" __declspec(dllexport) BOOL APIENTRY DllMain"); ModelFuncHdr=rdsDynStrCopy( "extern \"C\" __declspec(dllexport) int RDSCALL autocompModelFunc" ); Exported=rdsDynStrCopy("autocompModelFunc"); #else CompPath=rdsDynStrCopy( "$RDS$\\tdm-gcc\\bin\\g++.exe"); LinkPath=rdsDynStrCopy(CompPath); CompParams=rdsDynStrCopy( "-shared -fpermissive -c -I\"$RDSINCLUDE$\" \"$TEMP$\\$NAME$.cpp\"" ); LinkParams=rdsDynStrCopy( "-shared -static -static-libgcc -static-libstdc++ -o \"$TEMP$\\$NAME$.dll\" \"$TEMP$\\$NAME$.o\"" ); DllMainName=rdsDynStrCopy("extern \"C\" BOOL WINAPI DllMain"); ModelFuncHdr=rdsDynStrCopy( "extern \"C\" __declspec(dllexport) int RDSCALL autocompModelFunc"); Exported=rdsDynStrCopy("autocompModelFunc@12"); #endif }; // Деструктор класса ~TCAutoCompData(){ FreeAllStrings(); }; }; //========================================= // Запись параметров модуля в INI-файл void TCAutoCompData::WriteToIni(const char *IniFileName) { RDS_HOBJECT ini=rdsINICreateTextHolder(TRUE); // Загружаем старый текст из файла во вспомогательный объект, если он есть if(rdsFileExists(IniFileName,NULL,NULL,NULL)) rdsSetObjectStr(ini,RDS_HINI_LOADFILE,0,IniFileName); // Создаем секцию [Paths...] rdsSetObjectStr(ini,RDS_HINI_CREATESECTION,0,"Paths" RDS_PLATFORMNAME); // Записываем в нее пути rdsINIWriteString(ini,"Compiler",CompPath); rdsINIWriteString(ini,"Linker",LinkPath); rdsINIWriteString(ini,"Include",IncludePath); rdsINIWriteString(ini,"Lib",LibPath); rdsINIWriteBool(ini,"CompilerToPaths",CompSetPath); rdsINIWriteBool(ini,"LinkerToPaths",LinkSetPath); // Создаем секцию [Params...] rdsSetObjectStr(ini,RDS_HINI_CREATESECTION,0,"Params" RDS_PLATFORMNAME); // Записываем в нее параметры командной строки rdsINIWriteString(ini,"Compiler",CompParams); rdsINIWriteString(ini,"Linker",LinkParams); // Создаем секцию [Func...] rdsSetObjectStr(ini,RDS_HINI_CREATESECTION,0,"Func" RDS_PLATFORMNAME); // Записываем в нее остальные параметры rdsINIWriteString(ini,"DllMain",DllMainName); rdsINIWriteString(ini,"ModelFunc",ModelFuncHdr); rdsINIWriteString(ini,"Exported",Exported); // Сохраняем получившееся в файл rdsSetObjectStr(ini,RDS_HINI_SAVEFILE,0,TCAUTOCOMP_INI); // Уничтожение вспомогательного объекта rdsDeleteObject(ini); } //========================================= // Чтение параметров модуля из INI-файла void TCAutoCompData::ReadFromIni(const char *IniFileName) { RDS_HOBJECT ini=rdsINICreateTextHolder(TRUE); // Загружаем текст из файла во вспомогательный объект rdsSetObjectStr(ini,RDS_HINI_LOADFILE,0,IniFileName); // Проверяем, нет ли ошибок if(rdsCommandObject(ini,RDS_HINI_GETLASTERROR)) // Ошибка return; // Читаем строки из секции [Paths...] if(rdsINIOpenSection(ini,"Paths" RDS_PLATFORMNAME)) { char *CompPath_old=CompPath, // Старые значения *LinkPath_old=LinkPath, *IncludePath_old=IncludePath, *LibPath_old=LibPath; // Загружаем новые строки CompPath=rdsDynStrCopy(rdsINIReadString(ini,"Compiler",CompPath_old,NULL)); LinkPath=rdsDynStrCopy(rdsINIReadString(ini,"Linker",LinkPath_old,NULL)); IncludePath=rdsDynStrCopy(rdsINIReadString(ini,"Include",IncludePath_old,NULL)); LibPath=rdsDynStrCopy(rdsINIReadString(ini,"Lib",LibPath_old,NULL)); // Освобождаем старые строки rdsFree(CompPath_old); rdsFree(LinkPath_old); rdsFree(IncludePath_old); rdsFree(LibPath_old); // Добавление в пути CompSetPath=rdsINIReadBool(ini,"CompilerToPaths",CompSetPath); LinkSetPath=rdsINIReadBool(ini,"LinkerToPaths",LinkSetPath); } // Читаем строки из секции [Params...] if(rdsINIOpenSection(ini,"Params" RDS_PLATFORMNAME)) { char *CompParams_old=CompParams, // Старые значения *LinkParams_old=LinkParams; // Загружаем новые строки CompParams=rdsDynStrCopy(rdsINIReadString(ini,"Compiler",CompParams_old,NULL)); LinkParams=rdsDynStrCopy(rdsINIReadString(ini,"Linker",LinkParams_old,NULL)); // Освобождаем старые строки rdsFree(CompParams_old); rdsFree(LinkParams_old); } // Читаем строки из секции [Func...] if(rdsINIOpenSection(ini,"Func" RDS_PLATFORMNAME)) { char *DllMainName_old=DllMainName, // Старые значения *ModelFuncHdr_old=ModelFuncHdr, *Exported_old=Exported; // Загружаем новые строки DllMainName=rdsDynStrCopy(rdsINIReadString(ini,"DllMain",DllMainName_old,NULL)); ModelFuncHdr=rdsDynStrCopy(rdsINIReadString(ini,"ModelFunc",ModelFuncHdr_old,NULL)); Exported=rdsDynStrCopy(rdsINIReadString(ini,"Exported",Exported_old,NULL)); // Освобождаем старые строки rdsFree(DllMainName_old); rdsFree(ModelFuncHdr_old); rdsFree(Exported_old); } // Вспомогательный объект больше не нужен rdsDeleteObject(ini); } //========================================= // Настройка модуля автокомпиляции // ВАЖНО: Исходный текст программы должен быть записан в UTF8, // в противном случае необходимо использовать версии функций // с суффиксом "W" и символьные константы с префиксом "L" void TCAutoCompData::Setup(const char *IniFileName) { RDS_HOBJECT window; // Объект-окно const char exefilter[]= // Фильтр для диалога выбора файла "Исполняемые файлы (*.exe)|*.exe\nВсе файлы|*.*"; // Создание окна window=rdsFORMCreate(TRUE,-1,-1,"Параметры модуля"); // Создание вкладки rdsFORMAddTab(window,0,"Пути"); // Поле ввода выбора EXE-файла компилятора rdsFORMAddEdit(window,0,1,RDS_FORMCTRL_OPENDIALOG, "Компилятор:",300); rdsSetObjectStr(window,1,RDS_FORMVAL_LIST,exefilter); rdsSetObjectStr(window,1,RDS_FORMVAL_VALUE,CompPath); // Нужно устанавливать путь? rdsFORMAddEdit(window,0,100,RDS_FORMCTRL_CHECKBOX, "Добавлять папку в путь",300); rdsSetObjectInt(window,100,RDS_FORMVAL_VALUE,CompSetPath); // Поле ввода выбора EXE-файла редактора связей rdsFORMAddEdit(window,0,2,RDS_FORMCTRL_OPENDIALOG, "Редактор связей:",300); rdsSetObjectStr(window,2,RDS_FORMVAL_LIST,exefilter); rdsSetObjectStr(window,2,RDS_FORMVAL_VALUE,LinkPath); // Нужно устанавливать путь? rdsFORMAddEdit(window,0,200,RDS_FORMCTRL_CHECKBOX, "Добавлять папку в путь",300); rdsSetObjectInt(window,200,RDS_FORMVAL_VALUE,LinkSetPath); // Выбор папки файлов заголовков rdsFORMAddEdit(window,0,3,RDS_FORMCTRL_DIRDIALOG, "Папка заголовков:",300); rdsSetObjectStr(window,3,RDS_FORMVAL_VALUE,IncludePath); // Выбор папки файлов библиотек rdsFORMAddEdit(window,0,4,RDS_FORMCTRL_DIRDIALOG, "Папка библиотек:",300); rdsSetObjectStr(window,4,RDS_FORMVAL_VALUE,LibPath); // Создание вкладки rdsFORMAddTab(window,1,"Параметры"); // Параметры командной строки компилятора rdsFORMAddEdit(window,1,5,RDS_FORMCTRL_MULTILINE, "Параметры компилятора:",300); rdsSetObjectInt(window,5,RDS_FORMVAL_MLHEIGHT,3*24);// Высота rdsSetObjectStr(window,5,RDS_FORMVAL_VALUE,CompParams); // Параметры командной строки редактора связей rdsFORMAddEdit(window,1,6,RDS_FORMCTRL_MULTILINE, "Параметры редактора связей:",300); rdsSetObjectInt(window,6,RDS_FORMVAL_MLHEIGHT,3*24);// Высота rdsSetObjectStr(window,6,RDS_FORMVAL_VALUE,LinkParams); // Создание вкладки rdsFORMAddTab(window,2,"Описания"); // Имя главной функции rdsFORMAddEdit(window,2,7,RDS_FORMCTRL_EDIT, "Имя главной функции DLL:",300); rdsSetObjectStr(window,7,RDS_FORMVAL_VALUE,DllMainName); // Заголовок модели rdsFORMAddEdit(window,2,8,RDS_FORMCTRL_MULTILINE, "Заголовок функции модели:",300); rdsSetObjectInt(window,8,RDS_FORMVAL_MLHEIGHT,2*24);// Высота rdsSetObjectStr(window,8,RDS_FORMVAL_VALUE,ModelFuncHdr); // Экспортированное имя rdsFORMAddEdit(window,2,9,RDS_FORMCTRL_EDIT, "Экспортированное имя:",300); rdsSetObjectStr(window,9,RDS_FORMVAL_VALUE,Exported); // Открытие окна if(rdsFORMShowModalEx(window,NULL)) // Нажата OK { // Освобождаем старые строки параметров FreeAllStrings(); // Делаем динамические копии всех строк из полей ввода // и присваиваем их полям класса #define GETDYNRELPATH(x) rdsGetRelFilePath(x,rdsGetSystemPath(RDS_GSPAPPPATH),NULL) CompPath=GETDYNRELPATH(rdsGetObjectStr(window,1,RDS_FORMVAL_VALUE)); LinkPath=GETDYNRELPATH(rdsGetObjectStr(window,2,RDS_FORMVAL_VALUE)); IncludePath=GETDYNRELPATH(rdsGetObjectStr(window,3,RDS_FORMVAL_VALUE)); LibPath=GETDYNRELPATH(rdsGetObjectStr(window,4,RDS_FORMVAL_VALUE)); #undef GETDYNRELPATH CompParams=rdsDynStrCopy(rdsGetObjectStr(window,5,RDS_FORMVAL_VALUE)); LinkParams=rdsDynStrCopy(rdsGetObjectStr(window,6,RDS_FORMVAL_VALUE)); DllMainName=rdsDynStrCopy(rdsGetObjectStr(window,7,RDS_FORMVAL_VALUE)); ModelFuncHdr=rdsDynStrCopy(rdsGetObjectStr(window,8,RDS_FORMVAL_VALUE)); Exported=rdsDynStrCopy(rdsGetObjectStr(window,9,RDS_FORMVAL_VALUE)); CompSetPath=rdsGetObjectInt(window,100,RDS_FORMVAL_VALUE); LinkSetPath=rdsGetObjectInt(window,200,RDS_FORMVAL_VALUE); // Запись изменившихся параметров в INI-файл WriteToIni(IniFileName); } // Уничтожение окна rdsDeleteObject(window); } //========================================= // Функция модуля автокомпиляции extern "C" __declspec(dllexport) int RDSCALL TestCAutoComp( int CallMode, // Событие RDS_PCOMPMODULEDATA ModuleData, // Данные модуля LPVOID ExtParam) // Дополнительные параметры { // Приведение указателя на личную область данных // к правильному типу TCAutoCompData *data=(TCAutoCompData*)(ModuleData->ModuleData); switch(CallMode) { // Инициализация модуля case RDS_COMPM_INIT: // Создание личной области данных модуля ModuleData->ModuleData=data=new TCAutoCompData(); // Чтение параметров из INI-файла data->ReadFromIni(ModuleData->DataFile); break; // Очистка данных модуля case RDS_COMPM_CLEANUP: delete data; // Удаление личной области модуля break; // Вызов окна настройки модуля case RDS_COMPM_SETUP: data->Setup(ModuleData->DataFile); break; } return RDS_COMPR_DONE; } //=========================================