|
Работа 1С в внешними COM-объектами | ☑ | ||
---|---|---|---|---|
0
SpellKeeper
07.04.15
✎
12:10
|
Добрый день, коллеги.
Пытаюсь прикрутить к 1С некую внешнюю DLL. В этой DLL есть метод, который в качестве входного параметра требует значение типа Целое 64. Я так понимаю, что это Integer 64. Как известно, в 1С есть только тип Число разной длины. При попытке передачи переменной 1С в этот метод возвращается ошибка типа "Плохой тип переменной". Как я понимаю,1С конвертирует тип Число во что-то эдакое, что не понимает COm-объект. Вообще, значение, которое я пытаюсь передавать - это некий ИД записи из другой базы (не 1С). Com-объект так сделан, что надо сначала получить этот Ид из одного метода и передать в другой. Т.к. возвращаются ИД в виде списка, то я пытаюсь их класть в ТЗ с колонкой неопределенного вида. Однако в момент присваивания (или даже получения) 1С переваривает это значение в Число. Кто-нибудь может подсказать, как правильно передать такое значение? |
|||
1
бомболюк
07.04.15
✎
12:22
|
поиграйся с передачей параметра по значению, может приведет тип как надо.
|
|||
2
H A D G E H O G s
07.04.15
✎
12:26
|
ComSafeArray с элементом типа uint8
В метод передай одну ячейку этого массива |
|||
3
DrShad
07.04.15
✎
12:26
|
Base64Значение
Base64Строка может оно? |
|||
4
H A D G E H O G s
07.04.15
✎
12:29
|
(0) Ваще странная ситуация.
Так как там COM - то входящими параметрами метода могут быть только variant типы, которые легко и непринужденно конвертятся в нужные dll-ке типы (не нарушая сна). |
|||
5
DmitrO
07.04.15
✎
12:29
|
Дело в типах передаваемого значения VARIANT (стандартного для COM).
они бывают разных типов Твой COM объект ожидает либо VT_I8 либо VT_UI8. 1С при взаимодействии с COM принимает любые типы (в том числе и эти) в свой тип Число, однако передает она только так: если число целое передает его как VT_I4, если дробное VT_R8. Возможно, если целое число будет превышать 4 байта, то она передаст его как VT_I8. По идее COM объекты поддерживающие automation должны преобразовывать числа на входе если это допустимо, но видимо твой объект об этом не заботится. т.е. штатных способов не вижу. |
|||
6
H A D G E H O G s
07.04.15
✎
12:33
|
то она передаст его как VT_I8.
И какая разница? Его значение такое же, как и VT_UI8 до переполнения. И так же такое же после 2-х конвертаций VTUI8->VTI8->VTUI8 при переполнении. |
|||
7
DmitrO
07.04.15
✎
12:44
|
(6)вылазь из танка, целые числа она старается передать как VT_I4, но что она будет делать если передаваемое число попросту не войдет в 4 байта, а это любое число больше 2^32, да даже с учетом что она пытается в знаковый тип передать то больше 2^31 - я не знаю, надо проверять.
Но вероятнее всего это не спасет топикстартера, ибо изначально это число он получает от самого COM сервера. На сколько я понимаю, это сделано специально чтобы было меньше проблем с COM серверами, которые не делают преобразования на входе и ожидают VT_I4, в основном старые, примером одного такого является V77.Application. |
|||
8
Serginio1
07.04.15
✎
13:00
|
http://rsdn.ru/?Forum/Default.aspx?ans=1
Первое поле – VARTYPE, которое на самом деле является typedef-ом для unsigned short. Следующие три поля – WORD, еще один typedef для unsigned short. Итак, VARIANT – это 8 байт плюс размер union. Union содержит достаточно места для своего самого большого члена, в данном случае это 8 байт (для double, currency или date). Итак, VARIANT – это 16 байт. Однако есть одно исключение. В Variant поддерживается один забавный тип – DECIMAL. Вот его описание: struct tagDEC { USHORT wReserved; |
|||
9
H A D G E H O G s
07.04.15
✎
13:06
|
(8) Это все знают. Достаточно пошагово отладчиком delphi пройтись при присвоении значения.
|
|||
10
DmitrO
07.04.15
✎
13:06
|
кстати вот подтверждение из документации:
http://its.1c.ru/db/metod8dev#content:2262:hdoc Примитивные типы Значения NULL и Неопределено, а также типы данных Число, Строка, Дата, Булево, определенные в 1С:Предприятии, считаются примитивными. Они представляются аналогичными типами, определенными в VARIANT. Преобразование примитивных типов 1С:Предприятия в VARIANT представлено в таблице: Тип в 1С:Преприятии Тип VARIANT значение NULL VT_NULL значение Неопределено VT_EMPTY тип Число Целое в диапазоне от -2147483648 до 2147483647 VT_I4 Другие VT_R8 тип Строка VT_BSTR тип Дата VT_DATE тип Булево VT_BOOL Примитивные типы и значения, определенные в VARIANT, преобразуются в примитивные типы и значения 1С:Предприятия в соответствии со следующей таблицей. Тип VARIANT Тип в 1С:Предприятии VT_NULL значение NULL VT_EMPTY значение Неопределено VT_I2, VT_I4, VT_R4, VT_R8, VT_CY, VT_ERROR, VT_DECIMAL, VT_I1, VT_UI1, VT_UI2, VT_UI4, VT_I8, VT_UI8, VT_INT, VT_UINT тип Число VT_BSTR тип Строка VT_DATE тип Дата VT_BOOL тип Булево |
|||
11
DmitrO
07.04.15
✎
13:09
|
(9)а ты в своих COM серверах делаешь преобразование на входе? :)
|
|||
12
H A D G E H O G s
07.04.15
✎
13:10
|
(11) Конечно
function TBaseVKObject.GetParamAsByte(lIndex: Integer; minValue: byte = 0; maxValue: byte = 255): byte; var varGet: OleVariant; begin SafeArrayGetElement(g_Params, lIndex, varGet); try Result := varGet; except ErrorCode := -1 (lIndex + 1); ErrorDescription := 'Параметр номер ' + IntToStr(lIndex + 1) + ' не может быть преобразован в целое 1 байтовое баззнаковое.'; Raise Exception.Create(ErrorDescription); end; if (Result < minValue) or (Result > maxValue) then begin ErrorCode := -1 (lIndex + 51); Raise Exception.Create('Параметр номер ' + IntToStr(lIndex + 1) + ' преобразован в целое 1 байтовое баззнаковое, но его значение выходит за диапазон: "[' + IntToStr(minValue) + '..' + IntToStr(maxValue) + ']"'); end; end; |
|||
13
DmitrO
07.04.15
✎
13:13
|
(12)молодец, зачет тебе (!)
что делать топикстартеру с его горем? |
|||
14
DmitrO
07.04.15
✎
13:14
|
может через яваскрипт (MSSctriptControl) как нибудь можно извернуться? можно там явно задавать тип варианта?
|
|||
15
H A D G E H O G s
07.04.15
✎
13:14
|
ErrorCode у меня int64
положительные значения у меня - результаты GetLastError /HResult отрицательные значения до -50 у меня - ошибки преобразования входящих параметров, от -50 до -100 - выходы за размерности, не тот тип 1С объекта (вместо Массива - ТаблицаЗначений, и.т.д.) меньше -100 - мои ошибки |
|||
16
SpellKeeper
07.04.15
✎
13:46
|
Спасибо за ответы. Даже не ожидал что столько накидаете.
По идее ComSafeArray должен был бы подойти. Правда, при вызове метода SetValue ругается на неверный тип. Вот код: SA = новый ComSafeArray("VT_I8", 1); SA.SetValue(0,Выборка.IND); НовСтр.Ид = SA; Выборка.IND - это то самое значение. Написал все вроде правильно. Сейчас пытаюсь выяснить какой же на самом деле тип у этого IND. |
|||
17
DmitrO
07.04.15
✎
13:56
|
Да не поможет тебе ComSafeArray никак.
Да, там можно сделать массив нужного типа, но чтобы воспользоваться значением из этого массива, и передать в COM объект, тебе все равно придется его получить от туда.. угу, 1С его получит и преобразует опять в свое Число, ну и передавать будет дальше как обычно. |
|||
18
SpellKeeper
07.04.15
✎
14:11
|
Мда. Засада.
Буду знать. Вообще, я по другом выкрутился. Оказалось, что там то же самое можно получить несколько по-другому. Спасибо всем. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |