├── .gitignore ├── CMakeLists.txt ├── Compile.bat ├── Example.xml ├── Example ├── Forms │ ├── Form.xml │ ├── Form │ │ └── Ext │ │ │ ├── Form.xml │ │ │ └── Form │ │ │ └── Module.bsl │ ├── Test.xml │ └── Test │ │ └── Ext │ │ ├── Form.xml │ │ └── Form │ │ └── Module.bsl ├── Templates │ └── NativeAddIn.xml └── filename ├── LICENSE ├── README.md ├── appveyor.ps1 ├── appveyor.yml ├── build.sh ├── include ├── .gitattributes ├── AddInDefBase.h ├── ComponentBase.h ├── IMemoryManager.h ├── com.h └── types.h ├── manifest.ps1 ├── src ├── AddInNative.cpp ├── AddInNative.def ├── AddInNative.h ├── AddInNative.rc ├── TestComponent.cpp ├── TestComponent.h └── stdafx.h ├── take-screenshot.ps1 ├── template.xml └── version.h /.gitignore: -------------------------------------------------------------------------------- 1 | /database 2 | /build64Win 3 | /build32Win 4 | /build64Lin 5 | /build32Lin 6 | /build64 7 | /build32 8 | /build 9 | /tools 10 | /bin 11 | /.vc 12 | /.vs 13 | /.vscode 14 | /Autotest.log 15 | /Example/fileversion 16 | /Example/Templates/NativeAddIn/Ext/Template.bin 17 | /Decompile.bat 18 | manifest.xml 19 | *.epf 20 | *.o 21 | *.d 22 | *.so 23 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(NativeAddIn) 3 | set(TARGET NativeAddIn) 4 | 5 | add_library(${TARGET} SHARED 6 | src/AddInNative.cpp 7 | src/AddInNative.def 8 | src/AddInNative.h 9 | src/AddInNative.rc 10 | src/TestComponent.cpp 11 | src/TestComponent.h 12 | src/stdafx.h) 13 | 14 | target_compile_definitions(${TARGET} PRIVATE UNICODE _UNICODE) 15 | target_include_directories(${TARGET} PRIVATE include) 16 | set (LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/bin) 17 | set (EXECUTABLE_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH}) 18 | set (CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}) 19 | 20 | if (UNIX) 21 | if (APPLE) 22 | set(MySuffix1 "Mac") 23 | else(APPLE) 24 | set(MySuffix1 "Lin") 25 | endif(APPLE) 26 | if (TARGET_PLATFORM_32) 27 | set(MySuffix2 "32") 28 | else() 29 | set(MySuffix2 "64") 30 | endif() 31 | else(UNIX) 32 | if (NOT MSVC) 33 | message(FATAL_ERROR "Must be compiled with MSVC on Windows") 34 | endif(NOT MSVC) 35 | set(MyPrefix "lib") 36 | set(MySuffix1 "Win") 37 | endif(UNIX) 38 | 39 | set_target_properties( ${PROJECT_NAME} PROPERTIES 40 | OUTPUT_NAME ${MyPrefix}${PROJECT_NAME}${MySuffix1}${MySuffix2} 41 | POSITION_INDEPENDENT_CODE ON 42 | CXX_STANDARD_REQUIRED ON 43 | CXX_STANDARD 17 44 | ) 45 | 46 | if (UNIX) 47 | if (TARGET_PLATFORM_32) 48 | set(CMAKE_C_FLAGS "-m32 ${CMAKE_C_FLAGS}") 49 | set(CMAKE_CXX_FLAGS "-m32 ${CMAKE_CXX_FLAGS}") 50 | else(TARGET_PLATFORM_32) 51 | set(CMAKE_C_FLAGS "-m64 ${CMAKE_C_FLAGS}") 52 | set(CMAKE_CXX_FLAGS "-m64 ${CMAKE_CXX_FLAGS}") 53 | endif () 54 | target_link_libraries(${PROJECT_NAME} -static-libstdc++) 55 | else(UNIX) 56 | add_definitions(/MT) 57 | set(CMAKE_SUPPRESS_REGENERATION 1) 58 | set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE) 59 | target_compile_definitions(${TARGET} PRIVATE _WINDOWS 60 | _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING) 61 | target_compile_options(${TARGET} PRIVATE /utf-8) 62 | endif(UNIX) 63 | -------------------------------------------------------------------------------- /Compile.bat: -------------------------------------------------------------------------------- 1 | mkdir build32Win 2 | cd build32Win 3 | cmake .. -A Win32 -DMySuffix2=32 4 | cmake --build . --config Release 5 | cd .. 6 | 7 | mkdir build64Win 8 | cd build64Win 9 | cmake .. -A x64 -DMySuffix2=64 10 | cmake --build . --config Release 11 | cd .. 12 | -------------------------------------------------------------------------------- /Example.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | c3831ec8-d8d5-4f93-8a22-f9bfae07327f 7 | b6622ba9-c532-479a-b95b-39920ff960dc 8 | 9 | 10 | 383922ed-c955-4407-b2bd-96592d7e4ae9 11 | d45b137a-41d0-463e-b0d8-6712991436b7 12 | 13 | 14 | 15 | Example 16 | 17 | 18 | ru 19 | Example 20 | 21 | 22 | 23 | ExternalDataProcessor.Example.Form.Form 24 | 25 | 26 | 27 |
Form
28 |
Test
29 | 30 |
31 |
32 |
-------------------------------------------------------------------------------- /Example/Forms/Form.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 |
4 | 5 | Form 6 | 7 | 8 | ru 9 | Form 10 | 11 | 12 | 13 | Managed 14 | false 15 | 16 | PersonalComputer 17 | MobileDevice 18 | 19 | 20 | 21 |
22 |
-------------------------------------------------------------------------------- /Example/Forms/Form/Ext/Form.xml: -------------------------------------------------------------------------------- 1 |  2 |
3 | 4 | 5 | 10 | 15 | 16 | 17 | 18 | ПриСозданииНаСервере 19 | 20 | 21 | 22 | БольшоеЧисло 23 | 24 | 25 | 26 | 27 | ТипЗначения 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | cfg:ExternalDataProcessorObject.Example 36 | 37 | true 38 | 39 | 40 | 41 | <v8:item> 42 | <v8:lang>ru</v8:lang> 43 | <v8:content>Текущий каталог</v8:content> 44 | </v8:item> 45 | 46 | 47 | xs:string 48 | 49 | 0 50 | Variable 51 | 52 | 53 | 54 | 55 | 56 | <v8:item> 57 | <v8:lang>ru</v8:lang> 58 | <v8:content>Большое число</v8:content> 59 | </v8:item> 60 | 61 | 62 | xs:decimal 63 | 64 | 20 65 | 0 66 | Any 67 | 68 | 69 | 70 | 71 | 72 | <v8:item> 73 | <v8:lang>ru</v8:lang> 74 | <v8:content>Тип значения</v8:content> 75 | </v8:item> 76 | 77 | 78 | xs:decimal 79 | 80 | 0 81 | 0 82 | Any 83 | 84 | 85 | 86 | 87 | 88 | <v8:item> 89 | <v8:lang>ru</v8:lang> 90 | <v8:content>Метоположение компоненты</v8:content> 91 | </v8:item> 92 | 93 | 94 | xs:string 95 | 96 | 0 97 | Variable 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | <v8:item> 106 | <v8:lang>ru</v8:lang> 107 | <v8:content>Тест компоненты</v8:content> 108 | </v8:item> 109 | 110 | 111 | 112 | ru 113 | Тест компоненты 114 | 115 | 116 | ТестКомпоненты 117 | 118 | 119 | 120 | <v8:item> 121 | <v8:lang>ru</v8:lang> 122 | <v8:content>Автотест</v8:content> 123 | </v8:item> 124 | 125 | 126 | 127 | ru 128 | Автотест 129 | 130 | 131 | Автотест 132 | 133 | 134 |
-------------------------------------------------------------------------------- /Example/Forms/Form/Ext/Form/Module.bsl: -------------------------------------------------------------------------------- 1 | &НаСервере 2 | Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) 3 | 4 | 5 | ОбработкаОбъект = РеквизитФормыВЗначение("Объект"); 6 | МакетКомпоненты = ОбработкаОбъект.ПолучитьМакет("NativeAddIn"); 7 | МетоположениеКомпоненты = ПоместитьВоВременноеХранилище(МакетКомпоненты, УникальныйИдентификатор); 8 | 9 | ОбработкаОбъект = РеквизитФормыВЗначение("Объект"); 10 | ФайлОбработки = Новый Файл(ОбработкаОбъект.ИспользуемоеИмяФайла); 11 | ТекущийКаталог = ФайлОбработки.Путь; 12 | 13 | БольшоеЧисло = 3147483647; 14 | 15 | КонецПроцедуры 16 | 17 | &НаКлиенте 18 | Процедура ТестКомпоненты(Команда) 19 | 20 | УстановитьВнешнююКомпоненту(МетоположениеКомпоненты); 21 | ПодключитьВнешнююКомпоненту(МетоположениеКомпоненты, "TestAddin", ТипВнешнейКомпоненты.Native); 22 | ВнешняяКомпонента = Новый("AddIn.TestAddin.SimpleAlias"); 23 | 24 | Сообщить("Версия: " + ВнешняяКомпонента.Версия); 25 | 26 | ВнешняяКомпонента.TEXT = "Свойство: "; 27 | Сообщить(ВнешняяКомпонента.ТексТ); 28 | 29 | ВнешняяКомпонента.УстановитьТЕКСТ("Функция: "); 30 | Сообщить(ВнешняяКомпонента.ПолучитьТЕКСТ()); 31 | 32 | ВнешняяКомпонента.УстановитьТЕКСТ(); 33 | Сообщить(ВнешняяКомпонента.ПолучитьТЕКСТ()); 34 | 35 | ВнешняяКомпонента.Число = БольшоеЧисло; 36 | ТипЗначения = ВнешняяКомпонента.Число; 37 | 38 | КонецПроцедуры 39 | 40 | &НаКлиенте 41 | Процедура Автотест(Команда) 42 | 43 | Массив = СтрРазделить(ИмяФормы, "."); 44 | Массив[Массив.Количество() - 1] = "Test"; 45 | НовоеИмя = СтрСоединить(Массив, "."); 46 | ОткрытьФорму(НовоеИмя); 47 | 48 | КонецПроцедуры 49 | 50 | -------------------------------------------------------------------------------- /Example/Forms/Test.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 |
4 | 5 | Test 6 | 7 | 8 | ru 9 | Test 10 | 11 | 12 | 13 | Managed 14 | false 15 | 16 | PersonalComputer 17 | MobileDevice 18 | 19 | 20 | 21 |
22 |
-------------------------------------------------------------------------------- /Example/Forms/Test/Ext/Form.xml: -------------------------------------------------------------------------------- 1 |  2 |
3 | 4 | false 5 | 6 | 7 | ПриОткрытии 8 | ПриСозданииНаСервере 9 | 10 | 11 | 12 | Tree 13 | None 14 | true 15 | true 16 | true 17 | true 18 | Результаты 19 | 20 | 21 | 22 | 23 | 24 | Результаты 25 | SearchStringRepresentation 26 | 27 | 28 | 29 | 30 | 31 | 32 | Результаты 33 | ViewStatusRepresentation 34 | 35 | 36 | 37 | 38 | 39 | 40 | Результаты 41 | SearchControl 42 | 43 | 44 | 45 | 46 | 47 | 48 | Результаты.Наименование 49 | EnterOnInput 50 | 51 | 52 | 53 | 54 | Результаты.Выражение 55 | EnterOnInput 56 | 57 | 58 | 59 | 60 | Результаты.Значение 61 | EnterOnInput 62 | 63 | 64 | 65 | 66 | Результаты.ТекстОшибки 67 | EnterOnInput 68 | 69 | 70 | 71 | 72 |
73 | 74 | Items.Результаты.CurrentData.Подробности 75 | false 76 | true 77 | 78 | 79 | 80 |
81 | 82 | 83 | 84 | cfg:ExternalDataProcessorObject.Example 85 | 86 | true 87 | 88 | 89 | 90 | <v8:item> 91 | <v8:lang>ru</v8:lang> 92 | <v8:content>Результаты</v8:content> 93 | </v8:item> 94 | 95 | 96 | v8:ValueTree 97 | 98 | 99 | 100 | 101 | <v8:item> 102 | <v8:lang>ru</v8:lang> 103 | <v8:content>Ошибка</v8:content> 104 | </v8:item> 105 | 106 | 107 | xs:boolean 108 | 109 | 110 | 111 | 112 | <v8:item> 113 | <v8:lang>ru</v8:lang> 114 | <v8:content>Проблема</v8:content> 115 | </v8:item> 116 | 117 | 118 | xs:boolean 119 | 120 | 121 | 122 | 123 | <v8:item> 124 | <v8:lang>ru</v8:lang> 125 | <v8:content>Наименование</v8:content> 126 | </v8:item> 127 | 128 | 129 | xs:string 130 | 131 | 0 132 | Variable 133 | 134 | 135 | 136 | 137 | 138 | <v8:item> 139 | <v8:lang>ru</v8:lang> 140 | <v8:content>Выражение</v8:content> 141 | </v8:item> 142 | 143 | 144 | xs:string 145 | 146 | 0 147 | Variable 148 | 149 | 150 | 151 | 152 | 153 | <v8:item> 154 | <v8:lang>ru</v8:lang> 155 | <v8:content>Значение</v8:content> 156 | </v8:item> 157 | 158 | 159 | 160 | 161 | 162 | <v8:item> 163 | <v8:lang>ru</v8:lang> 164 | <v8:content>Текст ошибки</v8:content> 165 | </v8:item> 166 | 167 | 168 | xs:string 169 | 170 | 0 171 | Variable 172 | 173 | 174 | 175 | 176 | 177 | <v8:item> 178 | <v8:lang>ru</v8:lang> 179 | <v8:content>Подробности</v8:content> 180 | </v8:item> 181 | 182 | 183 | xs:string 184 | 185 | 0 186 | Variable 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | <v8:item> 195 | <v8:lang>ru</v8:lang> 196 | <v8:content>Список узлов</v8:content> 197 | </v8:item> 198 | 199 | 200 | v8:ValueListType 201 | 202 | 203 | 204 | 205 | 206 | 207 | Результаты 208 | 209 | 210 | 211 | 212 | AndGroup 213 | 214 | Результаты.Ошибка 215 | Equal 216 | false 217 | 218 | 219 | Результаты.Проблема 220 | Equal 221 | false 222 | 223 | 224 | 225 | 226 | 227 | ЦветФона 228 | #7FFF7F 229 | 230 | 231 | 232 | 233 | 234 | 235 | Результаты 236 | 237 | 238 | 239 | 240 | AndGroup 241 | 242 | Результаты.Проблема 243 | Equal 244 | true 245 | 246 | 247 | Результаты.Ошибка 248 | Equal 249 | false 250 | 251 | 252 | 253 | 254 | 255 | ЦветФона 256 | #FFFF96 257 | 258 | 259 | 260 | 261 | 262 | 263 | Результаты 264 | 265 | 266 | 267 | 268 | Результаты.Ошибка 269 | Equal 270 | true 271 | 272 | 273 | 274 | 275 | ЦветФона 276 | #FF7F7F 277 | 278 | 279 | 280 | 281 | 282 |
-------------------------------------------------------------------------------- /Example/Forms/Test/Ext/Form/Module.bsl: -------------------------------------------------------------------------------- 1 | &НаСервере 2 | Перем ВК, Лог; 3 | 4 | &НаКлиенте 5 | Процедура ПриОткрытии(Отказ) 6 | 7 | Для каждого ЭлементСписка из СписокУзлов Цикл 8 | Элементы.Результаты.Развернуть(ЭлементСписка.Значение, Истина); 9 | КонецЦикла; 10 | СписокУзлов.Очистить(); 11 | 12 | // ПодключитьОбработчикОжидания("ЗавершитьРаботу", 1, Истина); 13 | 14 | КонецПроцедуры 15 | 16 | &НаКлиенте 17 | Процедура ЗавершитьРаботу() 18 | 19 | ЗавершитьРаботуСистемы(Ложь); 20 | 21 | КонецПроцедуры 22 | 23 | &НаСервере 24 | Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) 25 | 26 | ОбработкаОбъект = РеквизитФормыВЗначение("Объект"); 27 | ФайлОбработки = Новый Файл(ОбработкаОбъект.ИспользуемоеИмяФайла); 28 | ТекущийКаталог = ФайлОбработки.Путь; 29 | 30 | ИдКомпоненты = "_" + StrReplace(New UUID, "-", ""); 31 | МакетКомпоненты = ОбработкаОбъект.ПолучитьМакет("NativeAddIn"); 32 | АдресКомпоненты = ПоместитьВоВременноеХранилище(МакетКомпоненты, УникальныйИдентификатор); 33 | ПодключитьВнешнююКомпоненту(АдресКомпоненты, ИдКомпоненты, ТипВнешнейКомпоненты.Native); 34 | ВК = Новый("AddIn." + ИдКомпоненты + ".SimpleAlias"); 35 | 36 | ВыполнитьТесты(); 37 | 38 | КонецПроцедуры 39 | 40 | &НаСервере 41 | Функция ТестВычислитьXML(ИмяКласса, ИмяТеста, Выражение) 42 | 43 | //Лог = Новый ЗаписьXML; 44 | //Лог.ОткрытьФайл(ТекущийКаталог + "autotest.log"); 45 | //Лог.ЗаписатьНачалоЭлемента("testsuites"); 46 | 47 | //Лог.ЗаписатьНачалоЭлемента("testsuite"); 48 | //Лог.ЗаписатьАтрибут("name", "Свойства"); 49 | //Лог.ЗаписатьАтрибут("timestamp", timestamp()); 50 | //Лог.ЗаписатьКонецЭлемента(); 51 | 52 | //Лог.ЗаписатьКонецЭлемента(); 53 | //Лог.Закрыть(); 54 | 55 | 56 | Лог.ЗаписатьНачалоЭлемента("testsuite"); 57 | Лог.ЗаписатьАтрибут("classname", ИмяКласса); 58 | Лог.ЗаписатьАтрибут("name", ИмяТеста); 59 | Попытка 60 | Значение = Вычислить(Выражение); 61 | Лог.ЗаписатьНачалоЭлемента("system-out"); 62 | Лог.ЗаписатьТекст(Значение); 63 | Лог.ЗаписатьКонецЭлемента(); 64 | Исключение 65 | Значение = Неопределено; 66 | Информация = ИнформацияОбОшибке(); 67 | Лог.ЗаписатьНачалоЭлемента("error"); 68 | Лог.ЗаписатьАтрибут("message", КраткоеПредставлениеОшибки(Информация)); 69 | Лог.ЗаписатьКонецЭлемента(); 70 | 71 | Лог.ЗаписатьНачалоЭлемента("system-err"); 72 | Лог.ЗаписатьТекст(ПодробноеПредставлениеОшибки(Информация)); 73 | Лог.ЗаписатьКонецЭлемента(); 74 | КонецПопытки; 75 | Лог.ЗаписатьКонецЭлемента(); 76 | 77 | Возврат Значение; 78 | 79 | КонецФункции 80 | 81 | &НаСервере 82 | Процедура ТестВыполнитьXML(ИмяКласса, ИмяТеста, Выражение) 83 | 84 | Лог.ЗаписатьНачалоЭлемента("testsuite"); 85 | Лог.ЗаписатьАтрибут("classname", ИмяКласса); 86 | Лог.ЗаписатьАтрибут("name", ИмяТеста); 87 | Попытка 88 | Выполнить(Выражение); 89 | Исключение 90 | Информация = ИнформацияОбОшибке(); 91 | Лог.ЗаписатьНачалоЭлемента("error"); 92 | Лог.ЗаписатьАтрибут("message", КраткоеПредставлениеОшибки(Информация)); 93 | Лог.ЗаписатьКонецЭлемента(); 94 | 95 | Лог.ЗаписатьНачалоЭлемента("system-err"); 96 | Лог.ЗаписатьТекст(ПодробноеПредставлениеОшибки(Информация)); 97 | Лог.ЗаписатьКонецЭлемента(); 98 | КонецПопытки; 99 | Лог.ЗаписатьКонецЭлемента(); 100 | 101 | КонецПроцедуры 102 | 103 | &НаСервере 104 | Функция timestamp() 105 | 106 | Возврат Формат(ТекущаяУниверсальнаяДата(), "ДФ=гггг-ММ-ддTчч:мм:сс"); 107 | 108 | КонецФункции 109 | 110 | &НаСервере 111 | Функция ПрочитатьСтрокуJSON(ТекстJSON) 112 | 113 | Если ПустаяСтрока(ТекстJSON) Тогда 114 | Возврат Неопределено; 115 | КонецЕсли; 116 | 117 | ПоляДаты = Новый Массив; 118 | ПоляДаты.Добавить("CreationDate"); 119 | ПоляДаты.Добавить("date"); 120 | 121 | ЧтениеJSON = Новый ЧтениеJSON(); 122 | ЧтениеJSON.УстановитьСтроку(ТекстJSON); 123 | Возврат ПрочитатьJSON(ЧтениеJSON, , ПоляДаты); 124 | 125 | КонецФункции 126 | 127 | &НаСервере 128 | Функция ДобавитьГруппуТестов(Наименование) 129 | 130 | Стр = Результаты.ПолучитьЭлементы().Добавить(); 131 | СписокУзлов.Добавить(Стр.ПолучитьИдентификатор()); 132 | Стр.Наименование = Наименование; 133 | Возврат Стр; 134 | 135 | КонецФункции 136 | 137 | &НаСервере 138 | Функция ТестВычислить(Группа, ИмяТеста, Выражение) 139 | 140 | Стр = Группа.ПолучитьЭлементы().Добавить(); 141 | Стр.Наименование = ИмяТеста; 142 | Стр.Выражение = Выражение; 143 | Попытка 144 | Значение = Вычислить(Выражение); 145 | Стр.Значение = Значение; 146 | Исключение 147 | Значение = Неопределено; 148 | Информация = ИнформацияОбОшибке(); 149 | Стр.ТекстОшибки = КраткоеПредставлениеОшибки(Информация); 150 | Стр.Подробности = ПодробноеПредставлениеОшибки(Информация); 151 | Стр.Ошибка = Истина; 152 | Группа.Ошибка = Истина; 153 | КонецПопытки; 154 | 155 | Возврат Значение; 156 | 157 | КонецФункции 158 | 159 | &НаСервере 160 | Процедура ТестВыполнить(Группа, ИмяТеста, Выражение) 161 | 162 | Стр = Группа.ПолучитьЭлементы().Добавить(); 163 | Стр.Наименование = ИмяТеста; 164 | Стр.Выражение = Выражение; 165 | Попытка 166 | Выполнить(Выражение); 167 | Исключение 168 | Значение = Неопределено; 169 | Информация = ИнформацияОбОшибке(); 170 | Стр.ТекстОшибки = КраткоеПредставлениеОшибки(Информация); 171 | Стр.Подробности = ПодробноеПредставлениеОшибки(Информация); 172 | Стр.Ошибка = Истина; 173 | Группа.Ошибка = Истина; 174 | КонецПопытки; 175 | 176 | КонецПроцедуры 177 | 178 | &НаСервере 179 | Процедура ВыполнитьТесты() 180 | 181 | Группа = ДобавитьГруппуТестов("Свойства компоненты"); 182 | ТестВычислить(Группа, "Получить:Version", "ВК.Version"); 183 | ТестВычислить(Группа, "Получить:Версия", "ВК.Версия"); 184 | ТестВычислить(Группа, "Получить:ВЕРСИЯ", "ВК.ВЕРСИЯ"); 185 | ТестВычислить(Группа, "Получить:Текст", "ВК.Текст"); 186 | ТестВычислить(Группа, "Получить:Проверка", "ВК.Проверка"); 187 | ТестВыполнить(Группа, "Установить:Версия", "ВК.Текст = ""Тест"""); 188 | ТестВыполнить(Группа, "Установить:Проверка", "ВК.Проверка = ""Тест"""); 189 | 190 | Группа = ДобавитьГруппуТестов("Методы компоненты"); 191 | ТестВыполнить(Группа, "УстановитьТекст()", "ВК.УстановитьТекст(""Тест"")"); 192 | ТестВычислить(Группа, "ПолучитьТекст()", "ВК.ПолучитьТекст()"); 193 | 194 | КонецПроцедуры -------------------------------------------------------------------------------- /Example/Templates/NativeAddIn.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 16 | -------------------------------------------------------------------------------- /Example/filename: -------------------------------------------------------------------------------- 1 | Example.epf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Kandrashin Denis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AddinTemplate - шаблон внешней компоненты 1С 2 | 3 | Для облегчения работы с шаблоном весь программный код, который не должен 4 | изменяться разработчиком при реализации собственных библиотек внешних 5 | компонент, собран в файлах **AddInNative.cpp** и **AddInNative.h**. 6 | 7 | Автор предлагает собственную оригинальную реализацию, которая хотя и лишена 8 | изящества шаблона [Infactum](https://github.com/Infactum/addin-template), 9 | тоже позволяет регистрировать компоненту под несколькими именами, 10 | использует лямбда-выражения для регистрации компоненты в библиотеке, при определении 11 | свойств и методов. При обращении к свойствам и методам регистр игнорируется. 12 | 13 | Отказ от использования шаблонов для определения процедур и функций в предлагаемой 14 | реализации компоненты накладывает существенные ограничения на формат лямбда выражений 15 | в методах **AddProperty**, **AddProcedure** и **AddFunction**, поскольку требует 16 | обязательного использования агрументов типа **VH** (короткий синоним **VariantHelper**). 17 | Это позволяет легко решить задачу возврата в 1С измененных значений параметров. 18 | Для возврата результата функции используется член базового класса **result**. 19 | 20 | Пример кода для регистрации компоненты в библиотеке: 21 | ```Cpp 22 | std::vector TestComponent::names = { 23 | AddComponent(u"AddInNative", []() { return new TestComponent; }), 24 | AddComponent(u"SimpleAlias", []() { return new TestComponent; }), 25 | }; 26 | 27 | TestComponent::TestComponent() 28 | { 29 | AddProperty(u"Text", u"Текст", 30 | [&](VH prop) { prop = this->getTestString(); }, 31 | [&](VH prop) { this->setTestString(prop); } 32 | ); 33 | 34 | AddFunction(u"GetText", u"ПолучитьТекст", 35 | [&]() { this->result = this->getTestString(); } 36 | ); 37 | 38 | AddProcedure(u"SetText", u"УстановитьТекст", 39 | [&](VH param) { this->setTestString(param); }, 40 | { {0, u"Default"} } 41 | ); 42 | } 43 | 44 | ``` 45 | -------------------------------------------------------------------------------- /appveyor.ps1: -------------------------------------------------------------------------------- 1 | $account = "lintest" 2 | $project = "AddinTemplate" 3 | $name = "NativeAddIn" 4 | 5 | #https://ci.appveyor.com/api-keys 6 | $token = $env:API_TOKEN 7 | $url1c = $env:URL_1CV8T 8 | $path = $env:APPVEYOR_BUILD_FOLDER 9 | $version = $env:APPVEYOR_BUILD_VERSION 10 | $postfix = '_' + $version -replace '\.', '_' 11 | Update-AppveyorBuild -Version "$version" 12 | Write-Output "Version: $version" 13 | 14 | $apiUrl = 'https://ci.appveyor.com/api' 15 | $headers = @{ 16 | "Authorization" = "Bearer $token" 17 | "Content-type" = "application/json" 18 | } 19 | 20 | $project = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/$account/$project/build/$version" -Headers $headers 21 | 22 | $jobId = $project.build.jobs[0].jobId 23 | $artifacts = Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts" -Headers $headers 24 | $artifactFileName = $artifacts[0].fileName 25 | 26 | Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/$artifactFileName" ` 27 | -OutFile "$path\Linux.zip" -Headers @{ "Authorization" = "Bearer $token" } 28 | 29 | Expand-Archive -Force -Path "$path\Linux.zip" -DestinationPath $path 30 | 31 | Rename-Item "$path\lib${name}Win32.dll" "${name}Win32$postfix.dll" 32 | Rename-Item "$path\lib${name}Win64.dll" "${name}Win64$postfix.dll" 33 | Rename-Item "$path\lib${name}Lin32.so" "${name}Lin32$postfix.so" 34 | Rename-Item "$path\lib${name}Lin64.so" "${name}Lin64$postfix.so" 35 | 36 | $compress = @{ 37 | Path = "$path\$name*.dll", "$path\$name*.so", "$path\manifest.xml" 38 | DestinationPath = "$path\AddIn.zip" 39 | } 40 | Compress-Archive @compress 41 | 42 | New-Item -ItemType Directory -Force -Path "$path\Example\Templates\$name\" | Out-Null 43 | New-Item -ItemType Directory -Force -Path "$path\Example\Templates\$name\Ext\" | Out-Null 44 | Copy-Item -Path "$path\AddIn.zip" -Destination "$path\Example\Templates\$name\Ext\Template.bin" 45 | 46 | $dist1c = "$path\1cv8.zip" 47 | if (!(Test-Path $dist1c)) { 48 | Write-Host "Download 1cv8.zip ..." 49 | Invoke-WebRequest -Uri $url1c -OutFile $dist1c 50 | } 51 | 52 | Write-Host "Expand archive 1cv8.zip ..." 53 | Expand-Archive -Force -Path $dist1c -DestinationPath $path 54 | Set-Content "$path\bin\conf\conf.cfg" "DisableUnsafeActionProtection=.*;" 55 | 56 | & "bin\1cv8t.exe" DESIGNER /F "$path\Data" /LoadExternalDataProcessorOrReportFromFiles "Example.xml" "$name.epf" /Out"Example.log" 57 | 58 | Write-Host "Process autotest..." 59 | #Start-Process "bin\1cv8ct.exe" -ArgumentList "/F $path\Autobase" -Wait 60 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 0.3.4.{build} 2 | configuration: Release 3 | platform: x64 4 | 5 | branches: 6 | only: 7 | - develop 8 | 9 | skip_branch_with_pr: true 10 | 11 | environment: 12 | global: 13 | URL_1CV8T: 14 | secure: z47uplaqZaQ0ZkroXy0GP00nv6ACPwovtb+EjfPgpS0IlWM6VQd+8apwLfqT9ndX 15 | API_TOKEN: 16 | secure: 85XpT8I1bxRTZaiIA+co0b5GS05J2VOn7PzunkYlL40= 17 | 18 | matrix: 19 | - APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu1804 20 | job_name: Linux 21 | - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 22 | job_depends_on: Linux 23 | job_name: Windows 24 | 25 | install: 26 | - sh: sudo dpkg --add-architecture i386 27 | - sh: sudo apt -qq update 28 | - sh: sudo apt -qq -y install uuid-dev 29 | - sh: sudo apt -qq -y install gcc-multilib g++-multilib 30 | 31 | init: 32 | - cmd: cmake --version 33 | - cmd: msbuild /version 34 | - cmd: echo. 35 | 36 | build_script: 37 | - sh: echo "#define VERSION_FULL " ${APPVEYOR_BUILD_VERSION} > "version.h" 38 | - cmd: Powershell.exe -File manifest.ps1 -Project NativeAddIn -Version %APPVEYOR_BUILD_VERSION% 39 | 40 | - mkdir build32 41 | - cd build32 42 | - sh: cmake -D CMAKE_BUILD_TYPE:STRING=Release -D TARGET_PLATFORM_32:BOOL=ON --build .. 43 | - cmd: cmake .. -A Win32 -DMySuffix2=32 44 | - cmake --build . --config Release 45 | - cd .. 46 | 47 | - mkdir build64 48 | - cd build64 49 | - sh: cmake -D CMAKE_BUILD_TYPE:STRING=Release -D TARGET_PLATFORM_32:BOOL=OFF --build .. 50 | - cmd: cmake .. -A x64 -DMySuffix2=64 51 | - cmake --build . --config Release 52 | - cd .. 53 | 54 | - sh: cp bin/libNativeAddInLin??.so . 55 | - sh: 7z a NativeAddIn.zip libNativeAddInLin??.so 56 | - cmd: copy bin\Release\libNativeAddInWin??.dll . 57 | - cmd: Powershell.exe -File appveyor.ps1 58 | 59 | for: 60 | - matrix: 61 | only: 62 | - job_name: Linux 63 | artifacts: 64 | - path: NativeAddIn.zip 65 | name: NativeAddIn 66 | 67 | - matrix: 68 | only: 69 | - job_name: Windows 70 | 71 | cache: 1cv8.zip 72 | 73 | artifacts: 74 | - path: AddIn.zip 75 | name: AddIn 76 | 77 | - path: NativeAddIn.epf 78 | name: NativeAddIn 79 | 80 | - path: example.log 81 | name: example log 82 | 83 | deploy: 84 | - provider: GitHub 85 | auth_token: 86 | secure: v7P89NQ2I5+WGNNdhpFrZEt6OCTPf8A8VSC5rttZMXh3DJ2fTChNEjZ1Wvm3kfBt 87 | repository: lintest/AddinTemplate 88 | artifact: AddIn.zip, NativeAddIn.epf 89 | draft: true 90 | prerelease: true 91 | force_update: true 92 | on: 93 | branch: develop 94 | APPVEYOR_REPO_TAG: true 95 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir build32Lin 4 | cd build32Lin 5 | cmake -D CMAKE_BUILD_TYPE:STRING=Release -D TARGET_PLATFORM_32:BOOL=ON --build .. 6 | cmake --build . 7 | cd .. 8 | 9 | mkdir build64Lin 10 | cd build64Lin 11 | cmake -D CMAKE_BUILD_TYPE:STRING=Release -D TARGET_PLATFORM_32:BOOL=OFF --build .. 12 | cmake --build . 13 | cd .. 14 | -------------------------------------------------------------------------------- /include/.gitattributes: -------------------------------------------------------------------------------- 1 | * -text 2 | -------------------------------------------------------------------------------- /include/AddInDefBase.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Warning!!! 3 | * DO NOT ALTER THIS FILE! 4 | */ 5 | 6 | #ifndef __ADAPTER_DEF_H__ 7 | #define __ADAPTER_DEF_H__ 8 | #include "types.h" 9 | 10 | struct IInterface 11 | { 12 | }; 13 | 14 | 15 | enum Interfaces 16 | { 17 | eIMsgBox = 0, 18 | eIPlatformInfo, 19 | 20 | #if defined(__ANDROID__) 21 | 22 | eIAndroidComponentHelper, 23 | 24 | #endif 25 | 26 | }; 27 | 28 | //////////////////////////////////////////////////////////////////////////////// 29 | /** 30 | * This class serves as representation of a platform for external 31 | * components External components use it to communicate with a platform. 32 | * 33 | */ 34 | /// Base interface for object components. 35 | class IAddInDefBase 36 | { 37 | public: 38 | virtual ~IAddInDefBase() {} 39 | /// Adds the error message 40 | /** 41 | * @param wcode - error code 42 | * @param source - source of error 43 | * @param descr - description of error 44 | * @param scode - error code (HRESULT) 45 | * @return the result of 46 | */ 47 | virtual bool ADDIN_API AddError(unsigned short wcode, const WCHAR_T* source, 48 | const WCHAR_T* descr, long scode) = 0; 49 | 50 | /// Reads a property value 51 | /** 52 | * @param wszPropName -property name 53 | * @param pVal - value being returned 54 | * @param pErrCode - error code (if any error occured) 55 | * @param errDescriptor - error description (if any error occured) 56 | * @return the result of read. 57 | */ 58 | virtual bool ADDIN_API Read(WCHAR_T* wszPropName, 59 | tVariant* pVal, 60 | long *pErrCode, 61 | WCHAR_T** errDescriptor) = 0; 62 | /// Writes a property value 63 | /** 64 | * @param wszPropName - property name 65 | * @param pVar - new property value 66 | * @return the result of write. 67 | */ 68 | virtual bool ADDIN_API Write(WCHAR_T* wszPropName, 69 | tVariant *pVar) = 0; 70 | 71 | ///Registers profile components 72 | /** 73 | * @param wszProfileName - profile name 74 | * @return the result of 75 | */ 76 | virtual bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName) = 0; 77 | 78 | /// Changes the depth of event buffer 79 | /** 80 | * @param lDepth - new depth of event buffer 81 | * @return the result of 82 | */ 83 | virtual bool ADDIN_API SetEventBufferDepth(long lDepth) = 0; 84 | /// Returns the depth of event buffer 85 | /** 86 | * @return the depth of event buffer 87 | */ 88 | virtual long ADDIN_API GetEventBufferDepth() = 0; 89 | /// Registers external event 90 | /** 91 | * @param wszSource - source of event 92 | * @param wszMessage - event message 93 | * @param wszData - message parameters 94 | * @return the result of 95 | */ 96 | virtual bool ADDIN_API ExternalEvent(WCHAR_T* wszSource, 97 | WCHAR_T* wszMessage, 98 | WCHAR_T* wszData) = 0; 99 | /// Clears event buffer 100 | /** 101 | */ 102 | virtual void ADDIN_API CleanEventBuffer() = 0; 103 | 104 | /// Sets status line contents 105 | /** 106 | * @param wszStatusLine - new status line contents 107 | * @return the result of 108 | */ 109 | virtual bool ADDIN_API SetStatusLine(WCHAR_T* wszStatusLine) = 0; 110 | /// Resets the status line contents 111 | /** 112 | * @return the result of 113 | */ 114 | virtual void ADDIN_API ResetStatusLine() = 0; 115 | }; 116 | 117 | class IAddInDefBaseEx : 118 | public IAddInDefBase 119 | { 120 | public: 121 | virtual ~IAddInDefBaseEx() {} 122 | 123 | virtual IInterface* ADDIN_API GetInterface(Interfaces iface) = 0; 124 | }; 125 | 126 | struct IMsgBox : 127 | public IInterface 128 | { 129 | virtual bool ADDIN_API Confirm(const WCHAR_T* queryText, tVariant* retVal) = 0; 130 | 131 | virtual bool ADDIN_API Alert(const WCHAR_T* text) = 0; 132 | }; 133 | 134 | struct IPlatformInfo : 135 | public IInterface 136 | { 137 | enum AppType 138 | { 139 | eAppUnknown = -1, 140 | eAppThinClient = 0, 141 | eAppThickClient, 142 | eAppWebClient, 143 | eAppServer, 144 | eAppExtConn, 145 | eAppMobileClient, 146 | eAppMobileServer, 147 | }; 148 | 149 | struct AppInfo 150 | { 151 | const WCHAR_T* AppVersion; 152 | const WCHAR_T* UserAgentInformation; 153 | AppType Application; 154 | }; 155 | 156 | virtual const AppInfo* ADDIN_API GetPlatformInfo() = 0; 157 | }; 158 | 159 | #endif //__ADAPTER_DEF_H__ 160 | -------------------------------------------------------------------------------- /include/ComponentBase.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Warning!!! 3 | * DO NOT ALTER THIS FILE! 4 | */ 5 | 6 | 7 | #ifndef __COMPONENT_BASE_H__ 8 | #define __COMPONENT_BASE_H__ 9 | 10 | #include "types.h" 11 | //////////////////////////////////////////////////////////////////////////////// 12 | /** 13 | * The given interface is intended for initialization and 14 | * uninitialization of component and its adjustments 15 | */ 16 | /// Interface of component initialization. 17 | class IInitDoneBase 18 | { 19 | public: 20 | virtual ~IInitDoneBase() {} 21 | /// Initializes component 22 | /** 23 | * @param disp - 1C:Enterpise interface 24 | * @return the result of 25 | */ 26 | virtual bool ADDIN_API Init(void* disp) = 0; 27 | /// Sets the memory manager 28 | /* 29 | * @param mem - pointer to memory manager interface. 30 | * @return the result of 31 | */ 32 | virtual bool ADDIN_API setMemManager(void* mem) = 0; 33 | 34 | /// Returns component version 35 | /** 36 | * @return - component version (2000 - version 2) 37 | */ 38 | virtual long ADDIN_API GetInfo() = 0; 39 | 40 | /// Uninitializes component 41 | /** 42 | * Component here should release all consumed resources. 43 | */ 44 | virtual void ADDIN_API Done() = 0; 45 | 46 | }; 47 | /////////////////////////////////////////////////////////////////////////// 48 | /** 49 | * The given interface defines methods that are intented to be used by the Platform 50 | */ 51 | /// Interface describing extension of language. 52 | class ILanguageExtenderBase 53 | { 54 | public: 55 | virtual ~ILanguageExtenderBase(){} 56 | /// Registers language extension 57 | /** 58 | * @param wsExtensionName - extension name 59 | * @return the result of 60 | */ 61 | virtual bool ADDIN_API RegisterExtensionAs(WCHAR_T** wsExtensionName) = 0; 62 | 63 | /// Returns number of component properties 64 | /** 65 | * @return number of properties 66 | */ 67 | virtual long ADDIN_API GetNProps() = 0; 68 | 69 | /// Finds property by name 70 | /** 71 | * @param wsPropName - property name 72 | * @return property index or -1, if it is not found 73 | */ 74 | virtual long ADDIN_API FindProp(const WCHAR_T* wsPropName) = 0; 75 | 76 | /// Returns property name 77 | /** 78 | * @param lPropNum - property index (starting with 0) 79 | * @param lPropAlias - 0 - international alias, 80 | * 1 - russian alias. (International alias is required) 81 | * @return proeprty name or 0 if it is not found 82 | */ 83 | virtual const WCHAR_T* ADDIN_API GetPropName(long lPropNum, 84 | long lPropAlias) = 0; 85 | 86 | /// Returns property value 87 | /** 88 | * @param lPropNum - property index (starting with 0) 89 | * @param pvarPropVal - the pointer to a variable for property value 90 | * @return the result of 91 | */ 92 | virtual bool ADDIN_API GetPropVal(const long lPropNum, 93 | tVariant* pvarPropVal) = 0; 94 | 95 | /// Sets the property value 96 | /** 97 | * @param lPropNum - property index (starting with 0) 98 | * @param varPropVal - the pointer to a variable for property value 99 | * @return the result of 100 | */ 101 | virtual bool ADDIN_API SetPropVal(const long lPropNum, 102 | tVariant* varPropVal) = 0; 103 | 104 | /// Is property readable? 105 | /** 106 | * @param lPropNum - property index (starting with 0) 107 | * @return true if property is readable 108 | */ 109 | virtual bool ADDIN_API IsPropReadable(const long lPropNum) = 0; 110 | 111 | /// Is property writable? 112 | /** 113 | * @param lPropNum - property index (starting with 0) 114 | * @return true if property is writable 115 | */ 116 | virtual bool ADDIN_API IsPropWritable(const long lPropNum) = 0; 117 | 118 | /// Returns number of component methods 119 | /** 120 | * @return number of component methods 121 | */ 122 | virtual long ADDIN_API GetNMethods() = 0; 123 | 124 | /// Finds a method by name 125 | /** 126 | * @param wsMethodName - method name 127 | * @return - method index 128 | */ 129 | virtual long ADDIN_API FindMethod(const WCHAR_T* wsMethodName) = 0; 130 | 131 | /// Returns method name 132 | /** 133 | * @param lMethodNum - method index(starting with 0) 134 | * @param lMethodAlias - 0 - international alias, 135 | * 1 - russian alias. (International alias is required) 136 | * @return method name or 0 if method is not found 137 | */ 138 | virtual const WCHAR_T* ADDIN_API GetMethodName(const long lMethodNum, 139 | const long lMethodAlias) = 0; 140 | 141 | /// Returns number of method parameters 142 | /** 143 | * @param lMethodNum - method index (starting with 0) 144 | * @return number of parameters 145 | */ 146 | virtual long ADDIN_API GetNParams(const long lMethodNum) = 0; 147 | 148 | /// Returns default value of method parameter 149 | /** 150 | * @param lMethodNum - method index(starting with 0) 151 | * @param lParamNum - parameter index (starting with 0) 152 | * @param pvarParamDefValue - the pointer to a variable for default value 153 | * @return the result of 154 | */ 155 | virtual bool ADDIN_API GetParamDefValue(const long lMethodNum, 156 | const long lParamNum, 157 | tVariant *pvarParamDefValue) = 0; 158 | 159 | /// Does the method have a return value? 160 | /** 161 | * @param lMethodNum - method index (starting with 0) 162 | * @return true if the method has a return value 163 | */ 164 | virtual bool ADDIN_API HasRetVal(const long lMethodNum) = 0; 165 | 166 | /// Calls the method as a procedure 167 | /** 168 | * @param lMethodNum - method index (starting with 0) 169 | * @param paParams - the pointer to array of method parameters 170 | * @param lSizeArray - the size of array 171 | * @return the result of 172 | */ 173 | virtual bool ADDIN_API CallAsProc(const long lMethodNum, 174 | tVariant* paParams, 175 | const long lSizeArray) = 0; 176 | 177 | /// Calls the method as a function 178 | /** 179 | * @param lMethodNum - method index (starting with 0) 180 | * @param pvarRetValue - the pointer to returned value 181 | * @param paParams - the pointer to array of method parameters 182 | * @param lSizeArray - the size of array 183 | * @return the result of 184 | */ 185 | virtual bool ADDIN_API CallAsFunc(const long lMethodNum, 186 | tVariant* pvarRetValue, 187 | tVariant* paParams, 188 | const long lSizeArray) = 0; 189 | }; 190 | /////////////////////////////////////////////////////////////////////////// 191 | /** 192 | * This interface is used to change component locale 193 | */ 194 | /// Base interface for component localization. 195 | class LocaleBase 196 | { 197 | public: 198 | virtual ~LocaleBase(){} 199 | /// Changes component locale 200 | /** 201 | * @param loc - new locale (for Windows - rus_RUS, 202 | * for Linux - ru_RU, etc...) 203 | */ 204 | virtual void ADDIN_API SetLocale(const WCHAR_T* loc) = 0; 205 | }; 206 | 207 | /////////////////////////////////////////////////////////////////////////// 208 | /** 209 | * The given interface is generalized, for its obligatory inheritance 210 | * in implementing components. 211 | */ 212 | /// Base interface describing object as a set of properties and methods. 213 | class IComponentBase : 214 | public IInitDoneBase, 215 | public ILanguageExtenderBase, 216 | public LocaleBase 217 | { 218 | public: 219 | virtual ~IComponentBase(){} 220 | }; 221 | 222 | enum AppCapabilities 223 | { 224 | eAppCapabilitiesInvalid = -1, 225 | eAppCapabilities1 = 1, 226 | eAppCapabilitiesLast = eAppCapabilities1, 227 | }; 228 | 229 | /// Announcements of exported functions 230 | /** 231 | * These functions should be implemented that component can be loaded and created. 232 | */ 233 | extern "C" long GetClassObject(const WCHAR_T*, IComponentBase** pIntf); 234 | extern "C" long DestroyObject(IComponentBase** pIntf); 235 | extern "C" const WCHAR_T* GetClassNames(); 236 | extern "C" AppCapabilities SetPlatformCapabilities(const AppCapabilities capabilities); 237 | 238 | typedef long (*GetClassObjectPtr)(const WCHAR_T* wsName, IComponentBase** pIntf); 239 | typedef long (*DestroyObjectPtr)(IComponentBase** pIntf); 240 | typedef const WCHAR_T* (*GetClassNamesPtr)(); 241 | typedef AppCapabilities (*SetPlatformCapabilitiesPtr)(const AppCapabilities capabilities); 242 | 243 | #endif //__COMPONENT_BASE_H__ 244 | -------------------------------------------------------------------------------- /include/IMemoryManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Warning!!! 3 | * DO NOT ALTER THIS FILE! 4 | */ 5 | 6 | 7 | #ifndef __IMEMORY_MANAGER_H__ 8 | #define __IMEMORY_MANAGER_H__ 9 | 10 | /////////////////////////////////////////////////////////////////////////////// 11 | /** 12 | * The given class allocates and releases memory for a component 13 | */ 14 | /// Interface representing memory manager. 15 | class IMemoryManager 16 | { 17 | public: 18 | virtual ~IMemoryManager() {} 19 | /// Allocates memory of specified size 20 | /** 21 | * @param pMemory - the double pointer to variable, that will hold newly 22 | * allocated block of memory of NULL if allocation fails. 23 | * @param ulCountByte - memory size 24 | * @return the result of 25 | */ 26 | virtual bool ADDIN_API AllocMemory (void** pMemory, unsigned long ulCountByte) = 0; 27 | /// Releases memory 28 | /** 29 | * @param pMemory - The double pointer to the memory block being released 30 | */ 31 | virtual void ADDIN_API FreeMemory (void** pMemory) = 0; 32 | }; 33 | 34 | #endif //__IMEMORY_MANAGER_H__ 35 | -------------------------------------------------------------------------------- /include/com.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __COM_H__ 3 | #define __COM_H__ 4 | 5 | #if defined(__linux__) || defined(__APPLE__) || defined(__ANDROID__) 6 | 7 | #ifdef __ANDROID__ 8 | 9 | typedef struct { 10 | unsigned int Data1; 11 | unsigned short Data2; 12 | unsigned short Data3; 13 | unsigned char Data4[ 8 ]; 14 | } uuid_t; 15 | 16 | #else 17 | #include 18 | #endif //__ANDROID__ 19 | 20 | #ifndef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ // iOS 21 | #include 22 | #endif //!__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ 23 | 24 | #pragma GCC system_header 25 | 26 | typedef long HRESULT; 27 | 28 | #ifdef __GNUC__ 29 | #define STDMETHODCALLTYPE __attribute__ ((__stdcall__)) 30 | #define DECLSPEC_NOTHROW __attribute__ ((nothrow)) 31 | #define STDMETHOD(method) virtual DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE method 32 | #else 33 | #define STDMETHODCALLTYPE 34 | #endif 35 | 36 | #define __stdcall STDMETHODCALLTYPE 37 | #define near 38 | #define far 39 | #define CONST const 40 | #define FAR far 41 | 42 | typedef unsigned long DWORD; 43 | #ifndef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ // iOS 44 | typedef int BOOL; 45 | #elif defined(__LP64__) 46 | typedef bool BOOL; 47 | #else 48 | typedef signed char BOOL; 49 | #endif //!__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ 50 | 51 | typedef void VOID; 52 | typedef short SHORT; 53 | typedef unsigned char BYTE; 54 | typedef unsigned short WORD; 55 | typedef float FLOAT; 56 | typedef FLOAT *PFLOAT; 57 | typedef BOOL near *PBOOL; 58 | typedef BOOL far *LPBOOL; 59 | typedef BYTE near *PBYTE; 60 | typedef BYTE far *LPBYTE; 61 | typedef int near *PINT; 62 | typedef int far *LPINT; 63 | typedef WORD near *PWORD; 64 | typedef WORD far *LPWORD; 65 | typedef long far *LPLONG; 66 | typedef DWORD near *PDWORD; 67 | typedef DWORD far *LPDWORD; 68 | typedef void far *LPVOID; 69 | typedef CONST void far *LPCVOID; 70 | typedef wchar_t *BSTR; 71 | typedef long SCODE; 72 | typedef int INT; 73 | typedef unsigned int UINT; 74 | typedef unsigned int *PUINT; 75 | typedef wchar_t WCHAR; 76 | typedef wchar_t OLECHAR; 77 | typedef wchar_t *LPOLESTR; 78 | typedef const wchar_t *LPCOLESTR; 79 | typedef DWORD LCID; 80 | typedef PDWORD PLCID; 81 | typedef long LONG; 82 | typedef unsigned long ULONG; 83 | typedef long long LONGLONG; 84 | typedef unsigned long long ULONGLONG; 85 | typedef LONG DISPID; 86 | typedef double DOUBLE; 87 | typedef double DATE; 88 | typedef short VARIANT_BOOL; 89 | typedef void *PVOID; 90 | typedef char CHAR; 91 | typedef CONST CHAR *LPCSTR; 92 | typedef unsigned short USHORT; 93 | typedef void *HMODULE; 94 | #define OLESTR(str) L##str 95 | 96 | typedef uuid_t GUID; 97 | typedef uuid_t IID; 98 | typedef uuid_t UUID; 99 | #define REFIID const IID & 100 | #define MAX_PATH 260 101 | 102 | #define IsEqualIID(x,y) uuid_compare((x),(y)) 103 | #ifdef __GNUC__ 104 | #define LoadLibraryA(x) dlopen((x), RTLD_LAZY) 105 | #define FreeLibrary(x) dlclose((x)) 106 | #define GetProcAddress(x, y) dlsym((x), (y)) 107 | #endif //__GNUC__ 108 | 109 | #define E_FAIL 0x80004005L 110 | #define S_OK 0L 111 | #define S_FALSE 1L 112 | #define E_NOINTERFACE 0x80004002L 113 | #define E_NOTIMPL 0x80004001L 114 | #define E_INVALIDARG 0x80070057L 115 | #define E_UNEXPECTED 0x8000FFFFL 116 | #define E_OUTOFMEMORY 0x8007000EL 117 | #define DISP_E_UNKNOWNNAME 0x80020006L 118 | #define DISPID_UNKNOWN ( -1 ) 119 | #define TRUE 1 120 | #define FALSE 0 121 | 122 | typedef long ITypeInfo; 123 | 124 | #if defined (__GNUC__) && !defined (NONAMELESSUNION) 125 | __extension__ /* no named members */ 126 | #endif 127 | union tCY { 128 | __extension__ struct 129 | { 130 | unsigned long Lo; 131 | long Hi; 132 | }; 133 | long long int64; 134 | }; 135 | typedef union tagCY CY; 136 | #define CLSIDFromString(x,y) uuid_parse((x),(unsigned char*)(y)) 137 | 138 | #endif //defined(__linux__) || defined(__APPLE__) 139 | 140 | #endif //__COM_H__ 141 | -------------------------------------------------------------------------------- /include/types.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __CON_TYPES_H__ 3 | #define __CON_TYPES_H__ 4 | 5 | #if defined(_WINDOWS) || defined(WINAPI_FAMILY) 6 | #include 7 | #endif 8 | 9 | #if defined(WINAPI_FAMILY) 10 | #include 11 | #endif 12 | 13 | #if __GNUC__ >=3 14 | #pragma GCC system_header 15 | #endif 16 | 17 | #include "com.h" 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #define EXTERN_C extern "C" 24 | 25 | #ifdef __GNUC__ 26 | #define _ANONYMOUS_UNION __extension__ 27 | #define _ANONYMOUS_STRUCT __extension__ 28 | #else 29 | #define _ANONYMOUS_UNION 30 | #define _ANONYMOUS_STRUCT 31 | #endif //__GNUC__ 32 | 33 | #ifdef NONAMELESSUNION 34 | #define __VARIANT_NAME_1 u 35 | #define __VARIANT_NAME_2 iface 36 | #define __VARIANT_NAME_3 str 37 | #define __VARIANT_NAME_4 wstr 38 | #else 39 | #define __VARIANT_NAME_1 40 | #define __VARIANT_NAME_2 41 | #define __VARIANT_NAME_3 42 | #define __VARIANT_NAME_4 43 | #endif //NONAMELESSUNION 44 | 45 | #define RESULT_FROM_ERRNO(x) ((long)(x) <= 0 ? ((long)(x)) \ 46 | : ((long) (((x) & 0x0000FFFF) | (BASE_ERRNO << 16) | 0x80000000))) 47 | 48 | #define ADDIN_E_NONE 1000 49 | #define ADDIN_E_ORDINARY 1001 50 | #define ADDIN_E_ATTENTION 1002 51 | #define ADDIN_E_IMPORTANT 1003 52 | #define ADDIN_E_VERY_IMPORTANT 1004 53 | #define ADDIN_E_INFO 1005 54 | #define ADDIN_E_FAIL 1006 55 | #define ADDIN_E_MSGBOX_ATTENTION 1007 56 | #define ADDIN_E_MSGBOX_INFO 1008 57 | #define ADDIN_E_MSGBOX_FAIL 1009 58 | 59 | #ifndef ADDIN_API 60 | #ifdef _WINDOWS 61 | #define ADDIN_API __stdcall 62 | #else 63 | //#define ADDIN_API __attribute__ ((__stdcall__)) 64 | #define ADDIN_API 65 | #endif //_WINDOWS 66 | #endif //ADDIN_API 67 | 68 | #include 69 | 70 | #ifdef _WINDOWS 71 | #define WCHAR_T wchar_t 72 | #else 73 | #define WCHAR_T uint16_t 74 | #endif //_WINDOWS 75 | typedef unsigned short TYPEVAR; 76 | enum ENUMVAR 77 | { 78 | VTYPE_EMPTY = 0, 79 | VTYPE_NULL, 80 | VTYPE_I2, //int16_t 81 | VTYPE_I4, //int32_t 82 | VTYPE_R4, //float 83 | VTYPE_R8, //double 84 | VTYPE_DATE, //DATE (double) 85 | VTYPE_TM, //struct tm 86 | VTYPE_PSTR, //struct str string 87 | VTYPE_INTERFACE, //struct iface 88 | VTYPE_ERROR, //int32_t errCode 89 | VTYPE_BOOL, //bool 90 | VTYPE_VARIANT, //struct _tVariant * 91 | VTYPE_I1, //int8_t 92 | VTYPE_UI1, //uint8_t 93 | VTYPE_UI2, //uint16_t 94 | VTYPE_UI4, //uint32_t 95 | VTYPE_I8, //int64_t 96 | VTYPE_UI8, //uint64_t 97 | VTYPE_INT, //int Depends on architecture 98 | VTYPE_UINT, //unsigned int Depends on architecture 99 | VTYPE_HRESULT, //long hRes 100 | VTYPE_PWSTR, //struct wstr 101 | VTYPE_BLOB, //means in struct str binary data contain 102 | VTYPE_CLSID, //UUID 103 | VTYPE_STR_BLOB = 0xfff, 104 | VTYPE_VECTOR = 0x1000, 105 | VTYPE_ARRAY = 0x2000, 106 | VTYPE_BYREF = 0x4000, //Only with struct _tVariant * 107 | VTYPE_RESERVED = 0x8000, 108 | VTYPE_ILLEGAL = 0xffff, 109 | VTYPE_ILLEGALMASKED = 0xfff, 110 | VTYPE_TYPEMASK = 0xfff 111 | } ; 112 | #if defined (__GNUC__) && !defined (NONAMELESSUNION) 113 | __extension__ /* no named members */ 114 | #endif 115 | struct _tVariant 116 | { 117 | _ANONYMOUS_UNION union 118 | { 119 | int8_t i8Val; 120 | int16_t shortVal; 121 | int32_t lVal; 122 | int intVal; 123 | unsigned int uintVal; 124 | int64_t llVal; 125 | uint8_t ui8Val; 126 | uint16_t ushortVal; 127 | uint32_t ulVal; 128 | uint64_t ullVal; 129 | int32_t errCode; 130 | long hRes; 131 | float fltVal; 132 | double dblVal; 133 | bool bVal; 134 | char chVal; 135 | wchar_t wchVal; 136 | DATE date; 137 | IID IDVal; 138 | struct _tVariant *pvarVal; 139 | struct tm tmVal; 140 | _ANONYMOUS_STRUCT struct 141 | { 142 | void* pInterfaceVal; 143 | IID InterfaceID; 144 | } __VARIANT_NAME_2/*iface*/; 145 | _ANONYMOUS_STRUCT struct 146 | { 147 | char* pstrVal; 148 | uint32_t strLen; //count of bytes 149 | } __VARIANT_NAME_3/*str*/; 150 | _ANONYMOUS_STRUCT struct 151 | { 152 | WCHAR_T* pwstrVal; 153 | uint32_t wstrLen; //count of symbol 154 | } __VARIANT_NAME_4/*wstr*/; 155 | } __VARIANT_NAME_1; 156 | uint32_t cbElements; //Dimension for an one-dimensional array in pvarVal 157 | TYPEVAR vt; 158 | }; 159 | typedef struct _tVariant tVariant; 160 | typedef tVariant tVariantArg; 161 | 162 | 163 | #if defined(NONAMELESSUNION) 164 | #define TV_JOIN(X, Y) ((X)->u.Y) 165 | #else 166 | #define TV_JOIN(X, Y) ((X)->Y) 167 | #endif 168 | 169 | #define TV_VT(X) ((X)->vt) 170 | #define TV_ISBYREF(X) (TV_VT(X)&VT_BYREF) 171 | #define TV_ISARRAY(X) (TV_VT(X)&VT_ARRAY) 172 | #define TV_ISVECTOR(X) (TV_VT(X)&VT_VECTOR) 173 | #define TV_NONE(X) TV_I2(X) 174 | 175 | #define TV_UI1(X) TV_JOIN(X, ui8Val) 176 | #define TV_I2(X) TV_JOIN(X, shortVal) 177 | #define TV_I4(X) TV_JOIN(X, lVal) 178 | #define TV_I8(X) TV_JOIN(X, llVal) 179 | #define TV_R4(X) TV_JOIN(X, fltVal) 180 | #define TV_R8(X) TV_JOIN(X, dblVal) 181 | #define TV_I1(X) TV_JOIN(X, i8Val) 182 | #define TV_UI2(X) TV_JOIN(X, ushortVal) 183 | #define TV_UI4(X) TV_JOIN(X, ulVal) 184 | #define TV_UI8(X) TV_JOIN(X, ullVal) 185 | #define TV_INT(X) TV_JOIN(X, intVal) 186 | #define TV_UINT(X) TV_JOIN(X, uintVal) 187 | 188 | #ifdef _WIN64 189 | #define TV_INT_PTR(X) TV_JOIN(X, llVal) 190 | #define TV_UINT_PTR(X) TV_JOIN(X, ullVal) 191 | #else 192 | #define TV_INT_PTR(X) TV_JOIN(X, lVal) 193 | #define TV_UINT_PTR(X) TV_JOIN(X, ulVal) 194 | #endif 195 | 196 | 197 | #define TV_DATE(X) TV_JOIN(X, date) 198 | #define TV_STR(X) TV_JOIN(X, pstrVal) 199 | #define TV_WSTR(X) TV_JOIN(X, pwstrVal) 200 | #define TV_BOOL(X) TV_JOIN(X, bVal) 201 | #define TV_UNKNOWN(X) TV_JOIN(X, pInterfaceVal) 202 | #define TV_VARIANTREF(X) TV_JOIN(X, pvarVal) 203 | 204 | void tVarInit(tVariant* tvar); 205 | 206 | inline 207 | void tVarInit(tVariant* tvar) 208 | { 209 | assert(tvar != NULL); 210 | memset(tvar, 0, sizeof(tVariant)); 211 | TV_VT(tvar) = VTYPE_EMPTY; 212 | } 213 | //----------------------------------------------------------------------------// 214 | // static setter functions... 215 | 216 | #define DATA_SET_BEGIN(data_) \ 217 | tVarInit(data_); 218 | 219 | #define DATA_SET_END(data_, type_) \ 220 | TV_VT(data_) = type_; 221 | 222 | 223 | #define DATA_SET(data_, type_, member_, value_) \ 224 | DATA_SET_BEGIN(data_) \ 225 | TV_JOIN(data_, member_) = value_; \ 226 | DATA_SET_END(data_, type_) 227 | 228 | #define DATA_SET_WITH_CAST(data_, type_, member_, cast_, value_) \ 229 | DATA_SET_BEGIN(data_) \ 230 | TV_JOIN(data_, member_) = cast_ value_; \ 231 | DATA_SET_END(data_, type_) 232 | 233 | #endif //__CON_TYPES_H__ 234 | -------------------------------------------------------------------------------- /manifest.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$project, 3 | [string]$version 4 | ) 5 | 6 | $postfix = '_' + $version -replace '\.','_' 7 | $v1,$v2,$v3,$v4 = $version.split('.') 8 | Set-Content 'version.h' "#define VER_FILENAME $project" 9 | Add-Content 'version.h' "#define VERSION_FULL $version" 10 | Add-Content 'version.h' "#define VERSION_MAJOR $v1" 11 | Add-Content 'version.h' "#define VERSION_MINOR $v2" 12 | Add-Content 'version.h' "#define VERSION_REVISION $v3" 13 | Add-Content 'version.h' "#define VERSION_BUILD $v4" 14 | 15 | $encoding = [System.Text.Encoding]::UTF8 16 | $writer = New-Object System.XMl.XmlTextWriter('./manifest.xml', $encoding) 17 | $writer.Formatting = 'Indented' 18 | $writer.Indentation = 1 19 | $writer.IndentChar = "`t" 20 | $writer.WriteStartDocument() 21 | $writer.WriteStartElement('bundle') 22 | $writer.WriteAttributeString('xmlns', 'http://v8.1c.ru/8.2/addin/bundle') 23 | 24 | $writer.WriteStartElement('component') 25 | $writer.WriteAttributeString('type', 'native') 26 | $writer.WriteAttributeString('os', 'Windows') 27 | $writer.WriteAttributeString('arch', 'i386') 28 | $writer.WriteAttributeString('path', "${project}Win32${postfix}.dll") 29 | $writer.WriteEndElement(); 30 | 31 | $writer.WriteStartElement('component') 32 | $writer.WriteAttributeString('type', 'native') 33 | $writer.WriteAttributeString('os', 'Windows') 34 | $writer.WriteAttributeString('arch', 'x86_64') 35 | $writer.WriteAttributeString('path', "${project}Win64${postfix}.dll") 36 | $writer.WriteEndElement(); 37 | 38 | $writer.WriteStartElement('component') 39 | $writer.WriteAttributeString('type', 'native') 40 | $writer.WriteAttributeString('os', 'Linux') 41 | $writer.WriteAttributeString('arch', 'i386') 42 | $writer.WriteAttributeString('path', "${project}Lin32${postfix}.so") 43 | $writer.WriteEndElement(); 44 | 45 | $writer.WriteStartElement('component') 46 | $writer.WriteAttributeString('type', 'native') 47 | $writer.WriteAttributeString('os', 'Linux') 48 | $writer.WriteAttributeString('arch', 'x86_64') 49 | $writer.WriteAttributeString('path', "${project}Lin64${postfix}.so") 50 | $writer.WriteEndElement(); 51 | 52 | $writer.WriteEndElement(); 53 | $writer.WriteEndDocument() 54 | $writer.Flush() 55 | $writer.Close() 56 | -------------------------------------------------------------------------------- /src/AddInNative.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include "../version.h" 4 | #define STRINGIZE2(s) #s 5 | #define STRINGIZE(s) STRINGIZE2(s) 6 | 7 | #ifdef _WINDOWS 8 | #pragma warning (disable : 4267) 9 | #pragma warning (disable : 4302) 10 | #pragma warning (disable : 4311) 11 | #else 12 | #include 13 | #include 14 | #include 15 | #endif 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "AddInNative.h" 27 | 28 | #ifdef _WINDOWS 29 | 30 | HMODULE hModule = NULL; 31 | 32 | BOOL APIENTRY DllMain(HMODULE module, DWORD ul_reason_for_call, LPVOID lpReserved) 33 | { 34 | switch (ul_reason_for_call) 35 | { 36 | case DLL_PROCESS_ATTACH: 37 | ::DisableThreadLibraryCalls(module); 38 | ::hModule = module; 39 | break; 40 | case DLL_THREAD_ATTACH: 41 | case DLL_THREAD_DETACH: 42 | case DLL_PROCESS_DETACH: 43 | break; 44 | } 45 | return TRUE; 46 | } 47 | #endif 48 | 49 | const WCHAR_T* GetClassNames() 50 | { 51 | static const std::u16string names(AddInNative::getComponentNames()); 52 | return (const WCHAR_T*)names.c_str(); 53 | } 54 | 55 | long GetClassObject(const WCHAR_T* wsName, IComponentBase** pInterface) 56 | { 57 | if (*pInterface) return 0; 58 | auto cls_name = std::u16string(reinterpret_cast(wsName)); 59 | return long(*pInterface = AddInNative::CreateObject(cls_name)); 60 | } 61 | 62 | long DestroyObject(IComponentBase** pInterface) 63 | { 64 | if (!*pInterface) return -1; 65 | delete* pInterface; 66 | *pInterface = nullptr; 67 | return 0; 68 | } 69 | 70 | std::string WC2MB(const std::wstring& wstr) 71 | { 72 | std::wstring_convert> converter; 73 | return converter.to_bytes(wstr); 74 | } 75 | 76 | std::wstring MB2WC(const std::string& str) 77 | { 78 | std::wstring_convert> converter; 79 | return converter.from_bytes(str); 80 | } 81 | 82 | std::map AddInNative::components; 83 | 84 | AddInNative::AddInNative(void) : result(nullptr, this) { 85 | AddProperty(u"Version", u"Версия", [&](VH var) { var = this->version(); }); 86 | } 87 | 88 | std::string AddInNative::version() 89 | { 90 | return STRINGIZE(VERSION_FULL); 91 | } 92 | 93 | bool AddInNative::Init(void* pConnection) 94 | { 95 | m_iConnect = static_cast(pConnection); 96 | if (m_iConnect) m_iConnect->SetEventBufferDepth(100); 97 | return m_iConnect != nullptr; 98 | } 99 | 100 | bool AddInNative::setMemManager(void* memory) 101 | { 102 | return m_iMemory = static_cast(memory); 103 | } 104 | 105 | long AddInNative::GetInfo() 106 | { 107 | return 2000; 108 | } 109 | 110 | void AddInNative::Done() 111 | { 112 | } 113 | 114 | bool AddInNative::RegisterExtensionAs(WCHAR_T** wsLanguageExt) 115 | { 116 | return *wsLanguageExt = W(name.c_str()); 117 | } 118 | 119 | long AddInNative::GetNProps() 120 | { 121 | return properties.size(); 122 | } 123 | 124 | long AddInNative::FindProp(const WCHAR_T* wsPropName) 125 | { 126 | std::u16string name((char16_t*)wsPropName); 127 | for (auto it = properties.begin(); it != properties.end(); ++it) { 128 | for (auto n = it->names.begin(); n != it->names.end(); ++n) { 129 | if (n->compare(name) == 0) return long(it - properties.begin()); 130 | } 131 | } 132 | name = upper(name); 133 | for (auto it = properties.begin(); it != properties.end(); ++it) { 134 | for (auto n = it->names.begin(); n != it->names.end(); ++n) { 135 | if (upper(*n).compare(name) == 0) return long(it - properties.begin()); 136 | } 137 | } 138 | return -1; 139 | } 140 | 141 | const WCHAR_T* AddInNative::GetPropName(long lPropNum, long lPropAlias) 142 | { 143 | try { 144 | auto it = std::next(properties.begin(), lPropNum); 145 | if (it == properties.end()) return nullptr; 146 | auto nm = std::next(it->names.begin(), lPropAlias); 147 | if (nm == it->names.end()) return nullptr; 148 | return W(nm->c_str()); 149 | } 150 | catch (...) { 151 | return nullptr; 152 | } 153 | } 154 | 155 | bool AddInNative::GetPropVal(const long lPropNum, tVariant* pvarPropVal) 156 | { 157 | auto it = std::next(properties.begin(), lPropNum); 158 | if (it == properties.end()) return false; 159 | if (!it->getter) return false; 160 | try { 161 | it->getter(VA(pvarPropVal, &(*it))); 162 | return true; 163 | } 164 | catch (const std::u16string& msg) { 165 | AddError(msg); 166 | return false; 167 | } 168 | catch (...) { 169 | return false; 170 | } 171 | } 172 | 173 | bool AddInNative::SetPropVal(const long lPropNum, tVariant* pvarPropVal) 174 | { 175 | auto it = std::next(properties.begin(), lPropNum); 176 | if (it == properties.end()) return false; 177 | if (!it->setter) return false; 178 | try { 179 | it->setter(VA(pvarPropVal, &(*it))); 180 | return true; 181 | } 182 | catch (const std::u16string& msg) { 183 | AddError(msg); 184 | return false; 185 | } 186 | catch (...) { 187 | return false; 188 | } 189 | } 190 | 191 | bool AddInNative::IsPropReadable(const long lPropNum) 192 | { 193 | auto it = std::next(properties.begin(), lPropNum); 194 | if (it == properties.end()) return false; 195 | return (bool)it->getter; 196 | } 197 | 198 | bool AddInNative::IsPropWritable(const long lPropNum) 199 | { 200 | auto it = std::next(properties.begin(), lPropNum); 201 | if (it == properties.end()) return false; 202 | return (bool)it->setter; 203 | } 204 | 205 | long AddInNative::GetNMethods() 206 | { 207 | return methods.size(); 208 | } 209 | 210 | long AddInNative::FindMethod(const WCHAR_T* wsMethodName) 211 | { 212 | std::u16string name((char16_t*)wsMethodName); 213 | for (auto it = methods.begin(); it != methods.end(); ++it) { 214 | for (auto n = it->names.begin(); n != it->names.end(); ++n) { 215 | if (n->compare(name) == 0) return long(it - methods.begin()); 216 | } 217 | } 218 | name = upper(name); 219 | for (auto it = methods.begin(); it != methods.end(); ++it) { 220 | for (auto n = it->names.begin(); n != it->names.end(); ++n) { 221 | if (upper(*n).compare(name) == 0) return long(it - methods.begin()); 222 | } 223 | } 224 | return -1; 225 | } 226 | 227 | const WCHAR_T* AddInNative::GetMethodName(const long lMethodNum, const long lMethodAlias) 228 | { 229 | try { 230 | auto it = std::next(methods.begin(), lMethodNum); 231 | if (it == methods.end()) return nullptr; 232 | auto nm = std::next(it->names.begin(), lMethodAlias); 233 | if (nm == it->names.end()) return nullptr; 234 | return W(nm->c_str()); 235 | } 236 | catch (...) { 237 | return nullptr; 238 | } 239 | } 240 | 241 | long AddInNative::GetNParams(const long lMethodNum) 242 | { 243 | auto it = std::next(methods.begin(), lMethodNum); 244 | if (it == methods.end()) return 0; 245 | if (std::get_if(&it->handler)) return 0; 246 | if (std::get_if(&it->handler)) return 1; 247 | if (std::get_if(&it->handler)) return 2; 248 | if (std::get_if(&it->handler)) return 3; 249 | if (std::get_if(&it->handler)) return 4; 250 | if (std::get_if(&it->handler)) return 5; 251 | if (std::get_if(&it->handler)) return 6; 252 | if (std::get_if(&it->handler)) return 7; 253 | return 0; 254 | } 255 | 256 | bool AddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant* pvarParamDefValue) 257 | { 258 | try { 259 | VA(pvarParamDefValue).clear(); 260 | auto it = std::next(methods.begin(), lMethodNum); 261 | if (it == methods.end()) return true; 262 | auto p = it->defs.find(lParamNum); 263 | if (p == it->defs.end()) return true; 264 | auto var = &p->second.variant; 265 | if (auto value = std::get_if(var)) { 266 | VA(pvarParamDefValue) = *value; 267 | return true; 268 | } 269 | if (auto value = std::get_if(var)) { 270 | VA(pvarParamDefValue) = *value; 271 | return true; 272 | } 273 | if (auto value = std::get_if(var)) { 274 | VA(pvarParamDefValue) = *value; 275 | return true; 276 | } 277 | if (auto value = std::get_if(var)) { 278 | VA(pvarParamDefValue) = *value; 279 | return true; 280 | } 281 | return true; 282 | } 283 | catch (const std::u16string& msg) { 284 | AddError(msg); 285 | return false; 286 | } 287 | catch (...) { 288 | return false; 289 | } 290 | } 291 | 292 | bool AddInNative::HasRetVal(const long lMethodNum) 293 | { 294 | try { 295 | auto it = std::next(methods.begin(), lMethodNum); 296 | if (it == methods.end()) return false; 297 | return it->hasRetVal; 298 | } 299 | catch (...) { 300 | return false; 301 | } 302 | } 303 | 304 | bool AddInNative::CallMethod(MethFunction* func, tVariant* p, Meth* m, const long lSizeArray) 305 | { 306 | if (auto handler = std::get_if(func)) { 307 | (*handler)(); 308 | return true; 309 | } 310 | if (auto handler = std::get_if(func)) { 311 | if (lSizeArray < 1) throw std::bad_function_call(); 312 | (*handler)(VA(p, m, 0)); 313 | return true; 314 | } 315 | if (auto handler = std::get_if(func)) { 316 | if (lSizeArray < 2) throw std::bad_function_call(); 317 | (*handler)(VA(p, m, 0), VA(p, m, 1)); 318 | return true; 319 | } 320 | if (auto handler = std::get_if(func)) { 321 | if (lSizeArray < 3) throw std::bad_function_call(); 322 | (*handler)(VA(p, m, 0), VA(p, m, 1), VA(p, m, 2)); 323 | return true; 324 | } 325 | if (auto handler = std::get_if(func)) { 326 | if (lSizeArray < 4) throw std::bad_function_call(); 327 | (*handler)(VA(p, m, 0), VA(p, m, 1), VA(p, m, 2), VA(p, m, 3)); 328 | return true; 329 | } 330 | if (auto handler = std::get_if(func)) { 331 | if (lSizeArray < 5) throw std::bad_function_call(); 332 | (*handler)(VA(p, m, 0), VA(p, m, 1), VA(p, m, 2), VA(p, m, 3), VA(p, m, 4)); 333 | return true; 334 | } 335 | if (auto handler = std::get_if(func)) { 336 | if (lSizeArray < 6) throw std::bad_function_call(); 337 | (*handler)(VA(p, m, 0), VA(p, m, 1), VA(p, m, 2), VA(p, m, 3), VA(p, m, 4), VA(p, m, 5)); 338 | return true; 339 | } 340 | if (auto handler = std::get_if(func)) { 341 | if (lSizeArray < 7) throw std::bad_function_call(); 342 | (*handler)(VA(p, m, 0), VA(p, m, 1), VA(p, m, 2), VA(p, m, 3), VA(p, m, 4), VA(p, m, 5), VA(p, m, 6)); 343 | return true; 344 | } 345 | return false; 346 | } 347 | 348 | bool AddInNative::CallAsProc(const long lMethodNum, tVariant* paParams, const long lSizeArray) 349 | { 350 | auto it = std::next(methods.begin(), lMethodNum); 351 | if (it == methods.end()) return false; 352 | try { 353 | result << VA(nullptr); 354 | return CallMethod(&it->handler, paParams, &(*it), lSizeArray); 355 | } 356 | catch (const std::u16string& msg) { 357 | AddError(msg); 358 | return false; 359 | } 360 | catch (...) { 361 | return false; 362 | } 363 | } 364 | 365 | bool AddInNative::CallAsFunc(const long lMethodNum, tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray) 366 | { 367 | auto it = std::next(methods.begin(), lMethodNum); 368 | if (it == methods.end()) return false; 369 | try { 370 | result << VA(pvarRetValue); 371 | bool ok = CallMethod(&it->handler, paParams, &(*it), lSizeArray); 372 | result << VA(nullptr); 373 | return ok; 374 | } 375 | catch (const std::u16string& msg) { 376 | AddError(msg); 377 | return false; 378 | } 379 | catch (...) { 380 | result << VA(nullptr); 381 | return false; 382 | } 383 | } 384 | 385 | void AddInNative::SetLocale(const WCHAR_T* locale) 386 | { 387 | std::string loc = WCHAR2MB(locale); 388 | this->alias = loc.substr(0, 3) == "rus"; 389 | } 390 | 391 | std::u16string AddInNative::getComponentNames() { 392 | const char16_t* const delim = u"|"; 393 | std::vector names; 394 | for (auto it = components.begin(); it != components.end(); ++it) names.push_back(it->first); 395 | std::basic_ostringstream, std::allocator> imploded; 396 | std::copy(names.begin(), names.end(), std::ostream_iterator>(imploded, delim)); 397 | std::u16string result = imploded.str(); 398 | result.pop_back(); 399 | return result; 400 | } 401 | 402 | std::u16string AddInNative::AddComponent(const std::u16string& name, CompFunction creator) 403 | { 404 | components.insert({ name, creator }); 405 | return name; 406 | } 407 | 408 | AddInNative* AddInNative::CreateObject(const std::u16string& name) { 409 | auto it = components.find(name); 410 | if (it == components.end()) return nullptr; 411 | AddInNative* object = it->second(); 412 | object->name = name; 413 | return object; 414 | } 415 | 416 | void AddInNative::AddProperty(const std::u16string& nameEn, const std::u16string& nameRu, const PropFunction& getter, const PropFunction& setter) 417 | { 418 | properties.push_back({ { nameEn, nameRu }, getter, setter }); 419 | } 420 | 421 | void AddInNative::AddProcedure(const std::u16string& nameEn, const std::u16string& nameRu, const MethFunction& handler, const MethDefaults& defs) 422 | { 423 | methods.push_back({ { nameEn, nameRu }, handler, defs, false }); 424 | } 425 | 426 | void AddInNative::AddFunction(const std::u16string& nameEn, const std::u16string& nameRu, const MethFunction& handler, const MethDefaults& defs) 427 | { 428 | methods.push_back({ { nameEn, nameRu }, handler, defs, true }); 429 | } 430 | 431 | bool ADDIN_API AddInNative::AllocMemory(void** pMemory, unsigned long ulCountByte) const 432 | { 433 | return m_iMemory ? m_iMemory->AllocMemory(pMemory, ulCountByte) : false; 434 | } 435 | 436 | void ADDIN_API AddInNative::FreeMemory(void** pMemory) const 437 | { 438 | if (m_iMemory) m_iMemory->FreeMemory(pMemory); 439 | } 440 | 441 | std::string AddInNative::WCHAR2MB(std::basic_string_view src) 442 | { 443 | #ifdef _WINDOWS 444 | static std::wstring_convert> cvt_utf8_utf16; 445 | return cvt_utf8_utf16.to_bytes(src.data(), src.data() + src.size()); 446 | #else 447 | static std::wstring_convert, char16_t> cvt_utf8_utf16; 448 | return cvt_utf8_utf16.to_bytes(reinterpret_cast(src.data()), 449 | reinterpret_cast(src.data() + src.size())); 450 | #endif//_WINDOWS 451 | } 452 | 453 | std::wstring AddInNative::WCHAR2WC(std::basic_string_view src) { 454 | #ifdef _WINDOWS 455 | return std::wstring(src); 456 | #else 457 | std::wstring_convert> conv; 458 | return conv.from_bytes(reinterpret_cast(src.data()), 459 | reinterpret_cast(src.data() + src.size())); 460 | #endif//_WINDOWS 461 | } 462 | 463 | std::u16string AddInNative::MB2WCHAR(std::string_view src) { 464 | #ifdef _WINDOWS 465 | static std::wstring_convert> cvt_utf8_utf16; 466 | std::wstring tmp = cvt_utf8_utf16.from_bytes(src.data(), src.data() + src.size()); 467 | return std::u16string(reinterpret_cast(tmp.data()), tmp.size()); 468 | #else 469 | static std::wstring_convert, char16_t> cvt_utf8_utf16; 470 | return cvt_utf8_utf16.from_bytes(src.data(), src.data() + src.size()); 471 | #endif//_WINDOWS 472 | } 473 | 474 | std::locale locale_ru = std::locale("ru_RU.UTF-8"); 475 | 476 | std::u16string AddInNative::upper(std::u16string& str) 477 | { 478 | std::transform(str.begin(), str.end(), str.begin(), [](wchar_t ch) { return std::toupper(ch, locale_ru); }); 479 | return str; 480 | } 481 | 482 | std::wstring AddInNative::upper(std::wstring& str) 483 | { 484 | std::transform(str.begin(), str.end(), str.begin(), [](wchar_t ch) { return std::toupper(ch, locale_ru); }); 485 | return str; 486 | } 487 | 488 | TYPEVAR AddInNative::VarinantHelper::type() 489 | { 490 | if (pvar == nullptr) throw std::bad_variant_access(); 491 | return pvar->vt; 492 | } 493 | 494 | uint32_t AddInNative::VarinantHelper::size() 495 | { 496 | if (pvar == nullptr) throw std::bad_variant_access(); 497 | if (pvar->vt != VTYPE_BLOB) throw error(VTYPE_BLOB); 498 | return pvar->strLen; 499 | } 500 | 501 | char* AddInNative::VarinantHelper::data() 502 | { 503 | if (pvar == nullptr) throw std::bad_variant_access(); 504 | if (pvar->vt != VTYPE_BLOB) throw error(VTYPE_BLOB); 505 | return pvar->pstrVal; 506 | } 507 | 508 | AddInNative::VarinantHelper& AddInNative::VarinantHelper::operator=(const std::string& str) 509 | { 510 | return operator=(AddInNative::MB2WCHAR(str)); 511 | } 512 | 513 | AddInNative::VarinantHelper& AddInNative::VarinantHelper::operator=(const std::wstring& str) 514 | { 515 | if (sizeof(wchar_t) == 2) { 516 | return operator=(std::u16string(reinterpret_cast(str.data()), str.size())); 517 | } 518 | else { 519 | return operator=(WC2MB(str)); 520 | } 521 | } 522 | 523 | void AddInNative::VarinantHelper::clear() 524 | { 525 | if (pvar == nullptr) throw std::bad_variant_access(); 526 | switch (TV_VT(pvar)) { 527 | case VTYPE_BLOB: 528 | case VTYPE_PWSTR: 529 | addin->FreeMemory(reinterpret_cast(&TV_WSTR(pvar))); 530 | break; 531 | } 532 | tVarInit(pvar); 533 | } 534 | 535 | AddInNative::VarinantHelper& AddInNative::VarinantHelper::operator=(int64_t value) 536 | { 537 | clear(); 538 | if (INT32_MIN <= value && value <= INT32_MAX) { 539 | TV_VT(pvar) = VTYPE_I4; 540 | TV_I4(pvar) = (int32_t)value; 541 | } 542 | else { 543 | TV_VT(pvar) = VTYPE_R8; 544 | TV_R8(pvar) = (double)value; 545 | } 546 | return *this; 547 | } 548 | 549 | AddInNative::VarinantHelper& AddInNative::VarinantHelper::operator=(double value) 550 | { 551 | clear(); 552 | TV_VT(pvar) = VTYPE_R8; 553 | TV_R8(pvar) = value; 554 | return *this; 555 | } 556 | 557 | AddInNative::VarinantHelper& AddInNative::VarinantHelper::operator=(bool value) 558 | { 559 | clear(); 560 | TV_VT(pvar) = VTYPE_BOOL; 561 | TV_BOOL(pvar) = value; 562 | return *this; 563 | } 564 | 565 | AddInNative::VarinantHelper& AddInNative::VarinantHelper::operator=(const std::u16string& str) 566 | { 567 | clear(); 568 | TV_VT(pvar) = VTYPE_PWSTR; 569 | pvar->pwstrVal = nullptr; 570 | size_t size = (str.size() + 1) * sizeof(char16_t); 571 | if (!addin->AllocMemory(reinterpret_cast(&pvar->pwstrVal), size)) throw std::bad_alloc(); 572 | memcpy(pvar->pwstrVal, str.c_str(), size); 573 | pvar->wstrLen = str.size(); 574 | while (pvar->wstrLen && pvar->pwstrVal[pvar->wstrLen - 1] == 0) pvar->wstrLen--; 575 | return *this; 576 | } 577 | 578 | bool AddInNative::AddError(const std::u16string& descr, long scode) 579 | { 580 | std::u16string info = u"AddIn." + name; 581 | return m_iConnect && m_iConnect->AddError(ADDIN_E_IMPORTANT, (WCHAR_T*)info.c_str(), (WCHAR_T*)descr.c_str(), scode); 582 | } 583 | 584 | static std::u16string typeinfo(TYPEVAR vt, bool alias) 585 | { 586 | switch (vt) { 587 | case VTYPE_EMPTY: 588 | return alias ? u"Неопределено" : u"Undefined"; 589 | case VTYPE_I2: 590 | case VTYPE_I4: 591 | case VTYPE_ERROR: 592 | case VTYPE_UI1: 593 | return alias ? u"Целое число" : u"Integer"; 594 | case VTYPE_BOOL: 595 | return alias ? u"Булево" : u"Boolean"; 596 | case VTYPE_R4: 597 | case VTYPE_R8: 598 | return alias ? u"Число" : u"Float"; 599 | case VTYPE_DATE: 600 | case VTYPE_TM: 601 | return alias ? u"Дата" : u"Date"; 602 | case VTYPE_PSTR: 603 | case VTYPE_PWSTR: 604 | return alias ? u"Строка" : u"String"; 605 | case VTYPE_BLOB: 606 | return alias ? u"Двоичные данные" : u"Binary"; 607 | default: 608 | return alias ? u"Неопределено" : u"Undefined"; 609 | } 610 | } 611 | 612 | std::exception AddInNative::VarinantHelper::error(TYPEVAR vt) const 613 | { 614 | std::basic_stringstream, std::allocator> ss; 615 | if (addin && addin->alias) { 616 | ss << u"Ошибка получения значения"; 617 | if (prop) ss << u" при обращении к свойству <" << prop->names[1] << ">"; 618 | if (meth) ss << u" при вызове метода <" << meth->names[1] << ">"; 619 | if (number >= 0) ss << u" параметр <" << number + 1 << ">"; 620 | ss << u" ожидается <" + typeinfo(vt, true) << u">"; 621 | if (pvar) ss << u" фактически <" + typeinfo(pvar->vt, true) << u">"; 622 | } 623 | else { 624 | ss << u"Error getting value"; 625 | if (prop) ss << u" of property <" << prop->names[0] << ">"; 626 | if (meth) ss << u" when calling method <" << meth->names[0] << ">"; 627 | if (number >= 0) ss << u" parameter <" << number + 1 << ">"; 628 | ss << u" expected <" + typeinfo(vt, false) << u">"; 629 | if (pvar) ss << u" actual value <" + typeinfo(pvar->vt, false) << u">"; 630 | } 631 | if (addin) addin->AddError(ss.str()); 632 | return std::bad_typeid(); 633 | } 634 | 635 | AddInNative::VarinantHelper::operator std::string() const 636 | { 637 | std::u16string str(*this); 638 | return WCHAR2MB((WCHAR_T*)str.c_str()); 639 | } 640 | 641 | AddInNative::VarinantHelper::operator std::wstring() const 642 | { 643 | std::u16string str(*this); 644 | return WCHAR2WC((WCHAR_T*)str.c_str()); 645 | } 646 | 647 | AddInNative::VarinantHelper::operator std::u16string() const 648 | { 649 | if (pvar == nullptr) throw std::bad_variant_access(); 650 | if (pvar->vt != VTYPE_PWSTR) throw error(VTYPE_PWSTR); 651 | return reinterpret_cast(pvar->pwstrVal); 652 | } 653 | 654 | AddInNative::VarinantHelper::operator int64_t() const 655 | { 656 | if (pvar == nullptr) throw std::bad_variant_access(); 657 | switch (TV_VT(pvar)) { 658 | case VTYPE_I2: 659 | case VTYPE_I4: 660 | case VTYPE_UI1: 661 | case VTYPE_ERROR: 662 | return (int64_t)pvar->lVal; 663 | case VTYPE_R4: 664 | case VTYPE_R8: 665 | return (int64_t)pvar->dblVal; 666 | default: 667 | throw error(VTYPE_I4); 668 | } 669 | } 670 | 671 | AddInNative::VarinantHelper::operator int() const 672 | { 673 | if (pvar == nullptr) throw std::bad_variant_access(); 674 | switch (TV_VT(pvar)) { 675 | case VTYPE_I2: 676 | case VTYPE_I4: 677 | case VTYPE_UI1: 678 | case VTYPE_ERROR: 679 | return (int)pvar->lVal; 680 | case VTYPE_R4: 681 | case VTYPE_R8: 682 | return (int)pvar->dblVal; 683 | default: 684 | throw error(VTYPE_I4); 685 | } 686 | } 687 | 688 | AddInNative::VarinantHelper::operator double() const 689 | { 690 | if (pvar == nullptr) throw std::bad_variant_access(); 691 | switch (TV_VT(pvar)) { 692 | case VTYPE_I2: 693 | case VTYPE_I4: 694 | case VTYPE_UI1: 695 | case VTYPE_ERROR: 696 | return (double)pvar->lVal; 697 | case VTYPE_R4: 698 | case VTYPE_R8: 699 | return (double)pvar->dblVal; 700 | default: 701 | throw error(VTYPE_R4); 702 | } 703 | } 704 | 705 | AddInNative::VarinantHelper::operator bool() const 706 | { 707 | if (pvar == nullptr) throw std::bad_variant_access(); 708 | switch (TV_VT(pvar)) { 709 | case VTYPE_BOOL: 710 | return TV_BOOL(pvar); 711 | case VTYPE_I2: 712 | case VTYPE_I4: 713 | case VTYPE_UI1: 714 | case VTYPE_ERROR: 715 | return (bool)pvar->lVal; 716 | default: 717 | throw error(VTYPE_BOOL); 718 | } 719 | } 720 | 721 | void AddInNative::VarinantHelper::AllocMemory(unsigned long size) 722 | { 723 | clear(); 724 | if (!addin->AllocMemory((void**)&pvar->pstrVal, size)) throw std::bad_alloc(); 725 | TV_VT(pvar) = VTYPE_BLOB; 726 | pvar->strLen = size; 727 | } 728 | 729 | WCHAR_T* AddInNative::W(const char16_t* str) const 730 | { 731 | WCHAR_T* res = NULL; 732 | size_t length = std::char_traits::length(str) + 1; 733 | unsigned long size = length * sizeof(WCHAR_T); 734 | if (!AllocMemory((void**)&res, size)) throw std::bad_alloc(); 735 | memcpy(res, str, size); 736 | return res; 737 | } 738 | 739 | -------------------------------------------------------------------------------- /src/AddInNative.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | GetClassObject 3 | DestroyObject 4 | GetClassNames 5 | -------------------------------------------------------------------------------- /src/AddInNative.h: -------------------------------------------------------------------------------- 1 | #ifndef __ADDINNATIVE_H__ 2 | #define __ADDINNATIVE_H__ 3 | 4 | #ifdef _WINDOWS 5 | #include 6 | #endif //_WINDOWS 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "ComponentBase.h" 15 | #include "AddInDefBase.h" 16 | #include "IMemoryManager.h" 17 | 18 | class AddInNative; 19 | 20 | class DefaultHelper { 21 | private: 22 | class EmptyValue {}; 23 | public: 24 | std::variant< 25 | EmptyValue, 26 | std::u16string, 27 | int64_t, 28 | double, 29 | bool 30 | > variant; 31 | public: 32 | DefaultHelper() : variant(EmptyValue()) {} 33 | DefaultHelper(const std::u16string& s) : variant(s) {} 34 | DefaultHelper(int64_t value) : variant(value) {} 35 | DefaultHelper(double value) : variant(value) {} 36 | DefaultHelper(bool value) : variant(value) {} 37 | DefaultHelper(const char16_t* value) { 38 | if (value) variant = std::u16string(value); 39 | else variant = EmptyValue(); 40 | } 41 | }; 42 | 43 | using CompFunction = std::function; 44 | 45 | class AddInNative : public IComponentBase 46 | { 47 | private: 48 | struct Prop; 49 | struct Meth; 50 | protected: 51 | class VarinantHelper { 52 | private: 53 | tVariant* pvar = nullptr; 54 | AddInNative* addin = nullptr; 55 | Prop* prop = nullptr; 56 | Meth* meth = nullptr; 57 | long number = -1; 58 | private: 59 | std::exception error(TYPEVAR vt) const; 60 | public: 61 | void AllocMemory(unsigned long size); 62 | VarinantHelper(const VarinantHelper& va) :pvar(va.pvar), addin(va.addin), prop(va.prop), meth(va.meth), number(va.number) {} 63 | VarinantHelper(tVariant* pvar, AddInNative* addin) :pvar(pvar), addin(addin) {} 64 | VarinantHelper(tVariant* pvar, AddInNative* addin, Prop* prop) :pvar(pvar), addin(addin), prop(prop) {} 65 | VarinantHelper(tVariant* pvar, AddInNative* addin, Meth* meth, long number) :pvar(pvar), addin(addin), meth(meth), number(number) {} 66 | VarinantHelper& operator<<(const VarinantHelper& va) { pvar = va.pvar; addin = va.addin; prop = va.prop, meth = va.meth, number = va.number; return *this; } 67 | VarinantHelper& operator=(const VarinantHelper& va) = delete; 68 | VarinantHelper& operator=(const std::string& str); 69 | VarinantHelper& operator=(const std::wstring& str); 70 | VarinantHelper& operator=(const std::u16string& str); 71 | VarinantHelper& operator=(int64_t value); 72 | VarinantHelper& operator=(double value); 73 | VarinantHelper& operator=(bool value); 74 | operator std::string() const; 75 | operator std::wstring() const; 76 | operator std::u16string() const; 77 | operator int64_t() const; 78 | operator double() const; 79 | operator bool() const; 80 | operator int() const; 81 | uint32_t size(); 82 | TYPEVAR type(); 83 | char* data(); 84 | void clear(); 85 | }; 86 | 87 | using VH = VarinantHelper; 88 | using MethDefaults = std::map; 89 | using PropFunction = std::function; 90 | using MethFunction0 = std::function; 91 | using MethFunction1 = std::function; 92 | using MethFunction2 = std::function; 93 | using MethFunction3 = std::function; 94 | using MethFunction4 = std::function; 95 | using MethFunction5 = std::function; 96 | using MethFunction6 = std::function; 97 | using MethFunction7 = std::function; 98 | 99 | using MethFunction = std::variant< 100 | MethFunction0, 101 | MethFunction1, 102 | MethFunction2, 103 | MethFunction3, 104 | MethFunction4, 105 | MethFunction5, 106 | MethFunction6, 107 | MethFunction7 108 | >; 109 | 110 | void AddProperty(const std::u16string& nameEn, const std::u16string& nameRu, const PropFunction &getter, const PropFunction &setter = nullptr); 111 | void AddProcedure(const std::u16string& nameEn, const std::u16string& nameRu, const MethFunction &handler, const MethDefaults &defs = {}); 112 | void AddFunction(const std::u16string& nameEn, const std::u16string& nameRu, const MethFunction &handler, const MethDefaults &defs = {}); 113 | static std::u16string AddComponent(const std::u16string& name, CompFunction creator); 114 | VarinantHelper result; 115 | 116 | static std::u16string upper(std::u16string& str); 117 | static std::wstring upper(std::wstring& str); 118 | static std::string WCHAR2MB(std::basic_string_view src); 119 | static std::wstring WCHAR2WC(std::basic_string_view src); 120 | static std::u16string MB2WCHAR(std::string_view src); 121 | WCHAR_T* W(const char16_t* str) const; 122 | static std::string version(); 123 | 124 | private: 125 | struct Prop { 126 | std::vector names; 127 | PropFunction getter; 128 | PropFunction setter; 129 | }; 130 | 131 | struct Meth { 132 | std::vector names; 133 | MethFunction handler; 134 | MethDefaults defs; 135 | bool hasRetVal; 136 | }; 137 | 138 | bool CallMethod(MethFunction* function, tVariant* paParams, Meth* meth, const long lSizeArray); 139 | VarinantHelper VA(tVariant* pvar) { return VarinantHelper(pvar, this); } 140 | VarinantHelper VA(tVariant* pvar, Prop* prop) { return VarinantHelper(pvar, this, prop); } 141 | VarinantHelper VA(tVariant* pvar, Meth* meth, long number) { return VarinantHelper(pvar + number, this, meth, number); } 142 | bool ADDIN_API AllocMemory(void** pMemory, unsigned long ulCountByte) const; 143 | void ADDIN_API FreeMemory(void** pMemory) const; 144 | bool AddError(const std::u16string& descr, long scode = 0); 145 | 146 | friend const WCHAR_T* GetClassNames(); 147 | static std::u16string getComponentNames(); 148 | friend long GetClassObject(const WCHAR_T*, IComponentBase**); 149 | static AddInNative* CreateObject(const std::u16string& name); 150 | 151 | static std::map components; 152 | std::vector properties; 153 | std::vector methods; 154 | std::u16string name; 155 | bool alias = false; 156 | 157 | public: 158 | AddInNative(void) ; 159 | virtual ~AddInNative() {} 160 | // IInitDoneBase 161 | virtual bool ADDIN_API Init(void*) override final; 162 | virtual bool ADDIN_API setMemManager(void* mem) override final; 163 | virtual long ADDIN_API GetInfo() override final; 164 | virtual void ADDIN_API Done() override final; 165 | // ILanguageExtenderBase 166 | virtual bool ADDIN_API RegisterExtensionAs(WCHAR_T** wsLanguageExt) override final; 167 | virtual long ADDIN_API GetNProps() override final; 168 | virtual long ADDIN_API FindProp(const WCHAR_T* wsPropName) override final; 169 | virtual const WCHAR_T* ADDIN_API GetPropName(long lPropNum, long lPropAlias) override final; 170 | virtual bool ADDIN_API GetPropVal(const long lPropNum, tVariant* pvarPropVal) override final; 171 | virtual bool ADDIN_API SetPropVal(const long lPropNum, tVariant* pvarPropVal) override final; 172 | virtual bool ADDIN_API IsPropReadable(const long lPropNum) override final; 173 | virtual bool ADDIN_API IsPropWritable(const long lPropNum) override final; 174 | virtual long ADDIN_API GetNMethods() override final; 175 | virtual long ADDIN_API FindMethod(const WCHAR_T* wsMethodName) override final; 176 | virtual const WCHAR_T* ADDIN_API GetMethodName(const long lMethodNum, const long lMethodAlias) override final; 177 | virtual long ADDIN_API GetNParams(const long lMethodNum) override final; 178 | virtual bool ADDIN_API GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant* pvarParamDefValue) override final; 179 | virtual bool ADDIN_API HasRetVal(const long lMethodNum) override final; 180 | virtual bool ADDIN_API CallAsProc(const long lMethodNum, tVariant* paParams, const long lSizeArray) override final; 181 | virtual bool ADDIN_API CallAsFunc(const long lMethodNum, tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray) override final; 182 | operator IComponentBase* () { return (IComponentBase*)this; }; 183 | // LocaleBase 184 | virtual void ADDIN_API SetLocale(const WCHAR_T* loc) override final; 185 | private: 186 | IMemoryManager* m_iMemory = nullptr; 187 | IAddInDefBase* m_iConnect = nullptr; 188 | }; 189 | #endif //__ADDINNATIVE_H__ 190 | -------------------------------------------------------------------------------- /src/AddInNative.rc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../version.h" 3 | 4 | #define STRINGIZE2(s) #s 5 | #define STRINGIZE(s) STRINGIZE2(s) 6 | 7 | #define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD 8 | #define VER_FILE_VERSION_STR STRINGIZE(VERSION_MAJOR) \ 9 | "." STRINGIZE(VERSION_MINOR) \ 10 | "." STRINGIZE(VERSION_REVISION) \ 11 | "." STRINGIZE(VERSION_BUILD) 12 | 13 | #define VER_FILE_DESCRIPTION_STR "Native AddIn for 1C" 14 | #define VER_COPYRIGHT_STR "Kandrashin Denis, 2020" 15 | #define VER_FILE_EXT ".dll" 16 | #define VER_FILE_STR STRINGIZE(VER_FILENAME) 17 | 18 | ///////////////////////////////////////////////////////////////////////////// 19 | 20 | #define APSTUDIO_READONLY_SYMBOLS 21 | 22 | #define VER_PRODUCTNAME_STR VER_FILE_STR 23 | #define VER_PRODUCT_VERSION VER_FILE_VERSION 24 | #define VER_PRODUCT_VERSION_STR VER_FILE_VERSION_STR 25 | #define VER_ORIGINAL_FILENAME_STR VER_FILE_STR VER_FILE_EXT 26 | #define VER_INTERNAL_NAME_STR VER_ORIGINAL_FILENAME_STR 27 | 28 | #ifdef _DEBUG 29 | #define VER_VER_DEBUG VS_FF_DEBUG 30 | #else 31 | #define VER_VER_DEBUG 0 32 | #endif 33 | 34 | #define VER_FILEOS VOS_NT_WINDOWS32 35 | #define VER_FILEFLAGS VER_VER_DEBUG 36 | 37 | ///////////////////////////////////////////////////////////////////////////// 38 | // 39 | // Version 40 | // 41 | VS_VERSION_INFO VERSIONINFO 42 | FILEVERSION VER_FILE_VERSION 43 | PRODUCTVERSION VER_PRODUCT_VERSION 44 | FILEFLAGSMASK 0x3fL 45 | FILEFLAGS VER_FILEFLAGS 46 | FILEOS VER_FILEOS 47 | FILETYPE VFT_DLL 48 | FILESUBTYPE 0x0L 49 | BEGIN 50 | BLOCK "StringFileInfo" 51 | BEGIN 52 | BLOCK "041904B0" 53 | BEGIN 54 | VALUE "FileDescription", VER_FILE_DESCRIPTION_STR "\0" 55 | VALUE "FileVersion", VER_FILE_VERSION_STR "\0" 56 | VALUE "InternalName", VER_INTERNAL_NAME_STR "\0" 57 | VALUE "LegalCopyright", VER_COPYRIGHT_STR "\0" 58 | VALUE "OriginalFilename", VER_ORIGINAL_FILENAME_STR "\0" 59 | VALUE "ProductName", VER_PRODUCTNAME_STR 60 | VALUE "ProductVersion", VER_PRODUCT_VERSION_STR "\0" 61 | END 62 | END 63 | BLOCK "VarFileInfo" 64 | BEGIN 65 | VALUE "Translation", 0x0419, 0x04B0 66 | END 67 | END 68 | -------------------------------------------------------------------------------- /src/TestComponent.cpp: -------------------------------------------------------------------------------- 1 | #include "TestComponent.h" 2 | 3 | std::vector TestComponent::names = { 4 | AddComponent(u"AddInNative", []() { return new TestComponent; }), 5 | AddComponent(u"SimpleAlias", []() { return new TestComponent; }), 6 | }; 7 | 8 | TestComponent::TestComponent() 9 | { 10 | AddProperty( 11 | u"Version", u"Версия", 12 | [&](VH var) { var = this->version(); }); 13 | 14 | AddProperty( 15 | u"Text", u"Текст", 16 | [&](VH var) { var = this->getTestString(); }, 17 | [&](VH var) { this->setTestString(var); }); 18 | 19 | AddProperty( 20 | u"Number", u"Число", 21 | [&](VH var) { var = this->value; }, 22 | [&](VH var) { this->value = var; }); 23 | 24 | AddFunction(u"GetText", u"ПолучитьТекст", [&]() { this->result = this->getTestString(); }); 25 | 26 | AddProcedure(u"SetText", u"УстановитьТекст", [&](VH par) { this->setTestString(par); }, {{0, u"default: "}}); 27 | } 28 | 29 | #include 30 | #include 31 | 32 | std::u16string TestComponent::getTestString() 33 | { 34 | time_t rawtime; 35 | struct tm *timeinfo; 36 | char buffer[255]; 37 | time(&rawtime); 38 | timeinfo = localtime(&rawtime); 39 | strftime(buffer, sizeof(buffer), "%d-%m-%Y %H:%M:%S", timeinfo); 40 | return text + MB2WCHAR(buffer); 41 | } 42 | 43 | void TestComponent::setTestString(const std::u16string &text) 44 | { 45 | this->text = text; 46 | } 47 | -------------------------------------------------------------------------------- /src/TestComponent.h: -------------------------------------------------------------------------------- 1 | #ifndef __TESTCOMPONENT_H__ 2 | #define __TESTCOMPONENT_H__ 3 | 4 | #include "AddInNative.h" 5 | 6 | class TestComponent: 7 | public AddInNative 8 | { 9 | private: 10 | static std::vector names; 11 | TestComponent(); 12 | int64_t value; 13 | private: 14 | std::u16string text; 15 | std::u16string getTestString(); 16 | void setTestString(const std::u16string &text); 17 | }; 18 | #endif //__TESTCOMPONENT_H__ -------------------------------------------------------------------------------- /src/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | #ifndef __STDAFX_H__ 6 | #define __STDAFX_H__ 7 | 8 | #ifdef _WINDOWS 9 | #include 10 | #endif //_WINDOWS 11 | 12 | #include 13 | 14 | std::wstring MB2WC(const std::string& source); 15 | std::string WC2MB(const std::wstring& source); 16 | 17 | #endif //__STDAFX_H__ 18 | -------------------------------------------------------------------------------- /take-screenshot.ps1: -------------------------------------------------------------------------------- 1 | [Reflection.Assembly]::LoadWithPartialName("System.Drawing") 2 | function screenshot([Drawing.Rectangle]$bounds, $path) { 3 | $bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height 4 | $graphics = [Drawing.Graphics]::FromImage($bmp) 5 | 6 | $graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size) 7 | 8 | $bmp.Save($path) 9 | 10 | $graphics.Dispose() 11 | $bmp.Dispose() 12 | } 13 | 14 | #NUC bounds 15 | $bounds = [Drawing.Rectangle]::FromLTRB(0, 0, 1280, 800) 16 | 17 | #remote display bounds 18 | #$bounds = [Drawing.Rectangle]::FromLTRB(0, 0, 1280, 800) 19 | 20 | $PC_name=$(Get-WmiObject Win32_Computersystem).name 21 | 22 | $dateandtime = Get-Date -Format yyyy-MM-dd-hh-mm-ss 23 | 24 | $path_pcname= "$env:appveyor_build_folder\" + $PC_name + "_screenshot_" + "$dateandtime"+ ".png" 25 | 26 | screenshot $bounds $path_pcname 27 | -------------------------------------------------------------------------------- /template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | errors="" 8 | failures="" 9 | name="" 10 | tests="" 11 | time="" 12 | > 13 | 14 | 16 | 18 | tests="" 19 | disabled="" 20 | errors="" 22 | failures="" 24 | hostname="" 25 | id="" 26 | package="" 27 | skipped="" 28 | time="" 29 | timestamp="" 30 | > 31 | 32 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | assertions="" 42 | classname="" 43 | status="" 44 | time="" 45 | > 46 | 47 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | type="" 60 | > 61 | 62 | 67 | 68 | type="" 69 | > 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /version.h: -------------------------------------------------------------------------------- 1 | #define VER_FILENAME AddinNative 2 | #define VERSION_FULL 0.3.3.0 3 | #define VERSION_MAJOR 0 4 | #define VERSION_MINOR 3 5 | #define VERSION_REVISION 3 6 | #define VERSION_BUILD 0 7 | --------------------------------------------------------------------------------