0. Evil Beaver 6364 22.04.13 12:41 Сейчас в теме

NativeAPI. Внешние компоненты на С++ "для чайников"

В жизни каждого 1С-ника наступает момент, когда для выполнения задачи требуется код на другом языке программирования. На помощь приходят внешние компоненты, но как их писать, если последний раз вы брались за другой язык сто лет назад, сортируя массивы пузырьком на лабораторках в ВУЗе? Можно быстренько узнать только самое нужное, прочитав эту статью.

Перейти к публикации

Комментарии
Избранное Подписка Сортировка: Древо
97. Evil Beaver 6364 10.08.18 12:47 Сейчас в теме
В С/С++ нет строк. Совсем. И объяснять что именно там вместо строк есть и как с этим жить - одного комментария не хватит.
98. Evil Beaver 6364 10.08.18 12:55 Сейчас в теме
Если взять Ваш кусок кода:

name = "Не удалось подключится к кассе"; // эти байты лежат на стеке текущего метода. После выхода из метода они уничтожатся.
// выделяем память, под строку, которую надо вернуть в 1С. Почему-то выделяем ее по адресу 3-го параметра... Скорее всего это неверно.
m_iMemory->AllocMemory((void**)&(paParams + 3)->pstrVal, sizeof(name));
TV_VT(paParams + 3) = VTYPE_PSTR;
TV_STR(paParams + 3) = name; // в указатель paParams[3]->pstrVal записали адрес байт, лежащих на стеке


// вернулись на уровень кода платформы

// 1. платформа передавала нам параметры метода как paParams, а ответ ждет в другом указателе - "что-то-там-result"
// 2. платформа грохает массив с переданными параметрами, т.к. он ей не нужен
// 3. в месте, где должен быть ответ - так и осталась пустая строка
// 4. память выделенная через AllocMemory - утекла или все-же по счастливой случайности освободилась (точнее скажут разрабы платформы).
99. markers 241 10.08.18 13:22 Сейчас в теме
(98) "в другом указателе - "что-то-там-result" это pvarRetValue? Странно, ибо
TV_VT(paParams + 2) = VTYPE_I4;
TV_INT(paParams + 2) = result;

передает в 1С значение result. Есть же входящие параметры и исходящие. Или я не правильно понял.
В любом случае, спасибо!
100. markers 241 28.08.18 07:40 Сейчас в теме
(99) Вот решение:
	name = "Failed to connect to VikiPrint";
	size = strlen(name);
	m_iMemory->AllocMemory((void**)&(paParams + 3)->pstrVal, size);
	TV_VT(paParams + 3) = VTYPE_PSTR;
	memcpy((void*)(paParams + 3)->pstrVal, name, size);
	(paParams + 3)->strLen = size;

Обратите внимание, чтоб возвращать сообщения на Русском языке, необходимо использовать функции получения размера и копирования значения в памяти для Unicode строк, ибо в ASCII таблице один символ занимает 1 байт и представленный в моём примере вариант получения размера строки под буфер strlen допустим для ASCII строк где размер занимаемый в памяти равняется количеству символов, но с Unicode таблицей это не работает, так как в ней каждый НЕ ASCII символ кодируется 2-4 байтами в зависимости от типа Unicode кодировки.
101. Evil Beaver 6364 28.08.18 18:50 Сейчас в теме
(100) Этот код некорректно будет работать с русскими буквами.

name - это неюникодная однобайтовая строка. Правильно объявить ее, как wchar_t, законвертить ее в двухбайтовую встроенным в шаблон компоненты методом и отправить в 1С, копируя в allocated-массив по 2 байта.
105. user617288_shanginre 06.02.19 08:14 Сейчас в теме
Коллеги, привет!

Такой важный вопрос. А внешнюю компоненту обязательно нужно делать только в вижуал студии, или можно в другой IDE сделать? По идее разницы никакой не должно быть, но спрашиваю на всякий случай, так как сами 1С на ИТС такую IDE рекомендовали...
106. tyasytova 29.06.19 18:07 Сейчас в теме
Большое спасибо! Собрала свою компоненту, но при подключении компоненты выходит ошибка {ВнешняяОбработка.СканированиеИРаспознавание.МодульОбъекта(302)}: Ошибка при вызове метода контекста (ПодключитьВнешнююКомпоненту)
КодВозврата = ПодключитьВнешнююКомпоненту("C:\repos\1CGetImageFragmentAddIn.dll", "1CGetImageFragmentAddIn", ТипВнешнейКомпоненты.Native);
по причине:
Недопустимое значение параметра (параметр номер '1') (Некорректное имя компоненты)
Может есть какие то тонкости по настройке проекта?
107. spacecraft 29.06.19 19:51 Сейчас в теме
(106)
КодВозврата = ПодключитьВнешнююКомпоненту("C:\repos\1CGetImageFragmentAddIn.dll", "1CGetImageFragmentAddIn", ТипВнешнейКомпоненты.Native);

Символическое имя компоненты не должно начинаться на цифру.
Из СП:

ПодключитьВнешнююКомпоненту(<Местоположение>, <Имя>, <Тип>)
Параметры:
<Имя> (обязательный)
Тип: Строка.
Символическое имя подключаемой внешнего компонента.
Имя должно удовлетворять правилам именования встроенного языка.
tyasytova; +1 Ответить
108. tyasytova 01.07.19 16:08 Сейчас в теме
(107) Спасибо помогло, компонента успешно устанавливается
И валится потом с ошибкой:
{ВнешняяОбработка.СканированиеИРаспознавание.МодульОбъекта(312)}: Тип не определен (AddIn.GetFragment.AddInNativeExtension)
109. markers 241 01.07.19 21:55 Сейчас в теме
(108)
	МакетСКомпонентой = "ОбщийМакет.ExtraComp";
	ИмяКомпоненты = "ExtraCompAddIn";
	ТребуетсяУстановкаКомпоненты = Не ПодключитьВнешнююКомпоненту(МакетСКомпонентой, ИмяКомпоненты);
	Если ТребуетсяУстановкаКомпоненты Тогда
		Попытка
			УстановитьВнешнююКомпоненту(МакетСКомпонентой);
			Если Не ПодключитьВнешнююКомпоненту(МакетСКомпонентой, ИмяКомпоненты) Тогда
				Возврат;
			КонецЕсли;
		Исключение
			Возврат;
		КонецПопытки;
	КонецЕсли;
	алкИнтерфейсКомпоненты = Новый("AddIn." + ИмяКомпоненты + "." + ИмяКомпоненты);
	алкКомпонентаПодключена = Истина;
	ВерсияКомпоненты = алкИнтерфейсКомпоненты.Version();
Показать
tyasytova; +1 Ответить
110. androgin 02.07.19 11:52 Сейчас в теме
(109) в исключении нужно выводить описание ошибки
111. markers 241 02.07.19 15:26 Сейчас в теме
(110) это уже по вкусу. Суть ответа не меняется. От куда копировал код, это не требовалось
112. heinzenberg 07.08.19 16:40 Сейчас в теме
Может кто подскажет, в чем может быть проблема.
Собираю компоненту из примера с итс, все работает.
Дополняю в *.h перечисление Methods. В *.cpp дополняю g_MethodNames, g_MethodNamesRu и методы HasRetVal, CallAsFunc. Собираю, ошибок нет.
При попытке установить внешнюю компоненту получаю ошибку: Установка внешней компоненты не выполнена! В процессе установки произошла ошибка! Возможно, отсутствует компонента для используемого клиентского приложения.

Возврат до первоначального состояния иногда приводит к работе, а иногда нет.
Что я не так делаю?
113. heinzenberg 07.08.19 16:51 Сейчас в теме
(112)upd
Видимо была проблема в том, что в рамках одного сеанса устанавливались несколько версий одной компоненты. При перезапуске 1С все чинится.
Оставьте свое сообщение
Новые вопросы с вознаграждением
Автор темы объявил вознаграждение за найденный ответ, его получит тот, кто первый поможет автору.

Вакансии

Программист, аналитик, эксперт 1С
Санкт-Петербург
По совместительству

Технический лидер, архитектор 1С, руководитель проектов
Санкт-Петербург
зарплата от 150 000 руб.
Полный день

Автор новостных обзоров на тему 1С и бухучета
Санкт-Петербург
По совместительству

Программист 1С
Екатеринбург
зарплата до 120 000 руб.
Полный день

Консультант-аналитик 1С
Рязань
зарплата до 80 000 руб.
Полный день