![]() |
|
Вопрос к гуру. Передача данных в 1С из COM | ☑ | ||
---|---|---|---|---|
0
O-Planet
01.10.13
✎
21:38
|
Такая проблема. Сделал com-объект, подключил в 1С, передал на вход некоего метода переменную из 1С, чтобы в нее записать что-то. Пишет, все ок. Но если длина данных превышает 16384 байта, то вываливается ошибка.
Срелда разработки - Builder c++ Кто знает, куда копать? В настройках не нашел ограничения типа 0х4000 Вот фрагмент кода. Может, не AnsiString использовать? STDMETHODIMP TConnectionImpl::Navigate(VARIANT* content) { AnsiString cont = ЧТОТО-GetMyAnsiString(); *content = static_cast<TVariant>(cont); } вот когда *content = static_cast<TVariant>(cont.SubString(1,16380)); то все работает И когда строка меньше 16380, то тоже работает (там, так понимаю, 4 байта на указатель еще) Кто поможет разобраться - тому от КУ и право на желтые штаны! |
|||
1
H A D G E H O G s
01.10.13
✎
21:42
|
Покажи код в 1С.
p.s. Если честно - нифига не понял. |
|||
2
Лефмихалыч
01.10.13
✎
21:46
|
(0) ты ВК состряпал или просто ActiveX? Что и нфига ты из 1С передаешь?
|
|||
3
O-Planet
01.10.13
✎
21:50
|
(2) ActiveX, т.е., подключил Automation Object к проекту. Передаю содержимое файла какого-то, чисто текст.
|
|||
4
O-Planet
01.10.13
✎
21:52
|
(1) В 1С все работает
Перем Контент; Попытка ХТТП=Новый COMОбъект("EasyHTTP.Connection"); Исключение ХТТП=Неопределено; Сообщить("Не подключился COM-объект!"); Возврат; КонецПопытки; Результат=ХТТП.Navigate(Контент); Если НЕ Результат Тогда Предупреждение(ХТТП.Error()); КонецЕсли; |
|||
5
H A D G E H O G s
01.10.13
✎
21:52
|
(3)
"Передаю содержимое файла какого-то, чисто текст." Откуда куда и как. ППЦ, я в шоке. |
|||
6
O-Planet
01.10.13
✎
21:56
|
(5) Ты, по ходу, еще и не в теме. Не так важно что, куда и откуда. Исходные данные: передаю текстовую строку AnsiString, в котором все буквы "А". Если их 16380 в строке, то все ЛЕТАЕТ и РАБОТАЕТ, как часы. Но если в строке 16381 символ, то вываливается ошибка.
|
|||
7
Apokalipsec
01.10.13
✎
21:57
|
AnsiString - класс динамической строки емкостью до 232-1 символов.
ы? |
|||
8
Лефмихалыч
01.10.13
✎
22:00
|
жаль форум хохот не передает, так бы все поржали над
>Ты, по ходу, еще и не в теме |
|||
9
O-Planet
01.10.13
✎
22:00
|
(5)
Что: текстовая строка Куда: из метода ActiveX-объекта в 1С Как: через OleVariant * (5) Там заявленная длина - 2 Гб. Если на форму выводить эту строку в TMemo, например, то все ОК. Похоже, стоит где-то какое-то ограничение именно на передачу через переменнцю типа Variant |
|||
10
Лефмихалыч
01.10.13
✎
22:00
|
(4) где код того, что и как ты передаешь?
|
|||
11
O-Planet
01.10.13
✎
22:02
|
(10) А в (0) - не код?
|
|||
12
O-Planet
01.10.13
✎
22:02
|
STDMETHODIMP TConnectionImpl::Navigate(VARIANT* content)
{ AnsiString cont = ЧТОТО-GetMyAnsiString(); *content = static_cast<TVariant>(cont); // ТУТА ПЕРЕДАЮ } |
|||
13
Лефмихалыч
01.10.13
✎
22:06
|
(11) код с другой стороны
|
|||
14
Лефмихалыч
01.10.13
✎
22:07
|
а, ты из COM-объекта в 1C пытаешься передать херову тонну буков, я понял
|
|||
15
O-Planet
01.10.13
✎
22:08
|
(13) В (4)
(14) Да |
|||
16
H A D G E H O G s
01.10.13
✎
22:09
|
(15) Ради прикола
project->Options-<Linking minimum stack size =40000, к примеру |
|||
17
H A D G E H O G s
01.10.13
✎
22:12
|
Еще ради прикола - добавь в процедуру 2 параметр, пусть Dword
У тебя строка обрежеться еще на 4 символа. |
|||
18
H A D G E H O G s
01.10.13
✎
22:12
|
Ну я так думаю
|
|||
19
O-Planet
01.10.13
✎
22:15
|
Не, не помогло. И не могло помочь. Потому что в строке все Ок, в Memo и файл она выводится. Не передается ТОЛЬКО через Variant *
Может WideString какой-нибудь спасет? И вообще есть какие-то ограничения на буфер памяти, который через VAriant можно передать? |
|||
20
H A D G E H O G s
01.10.13
✎
22:21
|
Вот хоть самому все проверять.
(19) А ты точно пересобрал проект? А можно подключиться? |
|||
21
O-Planet
01.10.13
✎
22:25
|
Итить! Точно пересобрал.
Домой иду, поздно уже ( Позадаю еще вопросы на винграде |
|||
22
Torquader
02.10.13
✎
00:21
|
Так как строка из символов по два байта, то порог в 32768, но в OLE нигде не сказано, что это так.
Вероятно, что кто-то перепутал int и long при передаче длины BSTR, который пихается в Variant. И (static cast) так никто не делает. Нужно сделать SysAllocString или пользоваться функциями работы с BSTR. |
|||
23
O-Planet
02.10.13
✎
03:44
|
Не, все неправы! Победил по-другому.
Вспомнилось неожиданно, что читал лет 15 назад, когда только изучал с++. Переменная Variant может ссылаться только на фрагмент памяти, ограниченный одним сегментом. Для Ole Automation поэтому рекомендуется использовать OleVariant Попробовал - заработало. Т.е., должно быть так: STDMETHODIMP TConnectionImpl::Navigate(VARIANT* content) { AnsiString cont = ЧТОТО-GetMyAnsiString(); OleVariant olecont = cont; *content = olecont; } ... и еще помогла музыка Mysty Edwards и болтовня в скайпе со старой подругой, которая сейчас живет в Такоме, и у них день типа. Эх, я бы мог тогда на ней жениться и сейчас бы работал в Майкрософт (тьфу-тьфу-тьфу) )) |
|||
24
strange2007
02.10.13
✎
04:48
|
Так что, жёлтые штаны ни кому не достались?
*ушёл за КЦ* |
|||
25
Кирпич
02.10.13
✎
09:45
|
Истины для.
(23) "Переменная Variant может ссылаться только на фрагмент памяти, ограниченный одним сегментом." Это в Windows 3.1 так было чтоли? "Для Ole Automation поэтому рекомендуется использовать OleVariant" Правильный ответ: В Ole Automation можно использовать ТОЛЬКО OleVariant. тип variant в Delphi и Builder имеет дополнительный тип PascalString с кодом $0100. и еще пару несовместимых с Ole типов. так что если такую переменную подсунешь Ole серверу, он тебя не поймет.(что и произошло) (17) Ты решил, что строки, как параметры процедуры, полностью в стек опускаются что-ли? Это противоречит здравому смыслу. (22) в BSTR влазит пару гигов. строка BSTR имеет четырехбайтный счетчик длины. "Так как строка из символов по два байта, то порог в 32768" ахринеть арифметика. ты чо там на чо умножал? или складывал? |
|||
26
H A D G E H O G s
02.10.13
✎
11:11
|
(25) "Ты решил, что строки, как параметры процедуры, полностью в стек опускаются что-ли? Это противоречит здравому смыслу."
Да, я так решил в порядке быстропроверяемого бреда. |
|||
27
Кирпич
02.10.13
✎
11:15
|
(26) ну для бреда сойдет. так то вариантная переменная имеет размер 16 байт и ты в неё строку хоть гигабайт запихай, она всё равно будет 16 байт.
|
|||
28
Кирпич
02.10.13
✎
11:19
|
+(27) ну а в параметрах процедуры обычно только указатель на эти 16 байт.
|
|||
29
O-Planet
02.10.13
✎
15:36
|
(25) "Истины для.
"Переменная Variant может ссылаться только на фрагмент памяти, ограниченный одним сегментом." Это в Windows 3.1 так было чтоли? " Мож что и не точно вспомнил, так как давно было. Может, там шла речь не о сегментах, а об адресном пространстве ))) Вот тогда почему в билдере конструктор этих самых интерфейсов не позволяет выбрать OleVariant, а только Variant? Хотя я юзаю BC++ 2007, может в более новых все лучше? |
|||
30
Torquader
03.10.13
✎
00:33
|
(25) Чего не так - длина в 32768 байт - это максимальное целое число в два байта (не забываем, что числа со знаком), если символы двухбайтовые, то их получается 16384.
BSTR, кстати, не только содержит 4 байта в начале, но и передаются как указатель на следующую за этими байтами строку. Поэтому Bstr - это специальный указатель, с которым работают специальные функции. И ещё, нужно помнить, что передача данных между процессами реально идёт через WM_COPYDATA, которая переносит область памяти из одного процесса в другой, и необходимо, чтобы в процессе было свободное виртуальное адресное пространство, иначе будет ошибка передачи. Поэтому, большие объёмы данных рекомендуется передавать между процессами через файлы, проецируемые в память (можно проецировать сразу файл подкачки и размер файла в длинное целое восьмибайтовое число). Если уж хочется вспомнить про сегменты, то это было в DOS-е в реальном режиме. А в Windows 3.1 уже был защищённый режим с 32-битными указателями, когда можно было превысить границу в 64 Кб (а не 32, как кто-то тут вспомнил). 32Кб - было ограничение размера кластера в FAT-е. |
|||
31
Кирпич
03.10.13
✎
08:42
|
(29) "конструктор этих самых интерфейсов не позволяет выбрать OleVariant, а только Variant? "
конструктор тебе позволяет выбрать VARIANT а не Variant. VARIANT - это структура, а Variant это класс. OleVariant тоже класс. Эти классы ты можешь внутри своего COM сервера, а принимать параметры ты можешь только в VARIANT. |
|||
32
Кирпич
03.10.13
✎
08:51
|
(30) "Чего не так - длина в 32768 байт - это максимальное целое число в два байта (не забываем, что числа со знаком), если символы двухбайтовые, то их получается 16384. "
Ты чо издеваешься чтоли? При чем тут длина символа и длина строки? Хочешь сказать, что я не могу создать строку с однобайтовыми символами длиной больше 255? Это кто мне запретит то? Сам же пишешь, что BSTR содержит 4 байта в начале. В этих четырех байтах и записана длина строки. Вот и считай какая может быть длина строки. |
|||
33
Кирпич
03.10.13
✎
08:53
|
(32) "не забываем, что числа со знаком" это какой дурак будет длину строки мерить со здаком. Длина строки -7 чтоли?
|
|||
34
Кирпич
03.10.13
✎
09:25
|
(30) и передачу данных между процессами ты чего приплел?
никто вроде не собирался передавать строки между процессами. |
|||
35
hhhh
03.10.13
✎
09:25
|
(30) не так. Два байта это 65536.
не забываем, что числа со знаком, получаем 32768 |
|||
36
Кирпич
03.10.13
✎
09:25
|
чота я сам с собой ругаюсь :)
|
|||
37
Кирпич
03.10.13
✎
09:27
|
(35) какие два байта? вы их откуда берете? у нас четыре байта. Это два гига. Делим на два, получаем два гига в символах.
|
|||
38
Кирпич
03.10.13
✎
09:28
|
+(37) блин. 4 байта, 4 гига, 2 гига длина строки
|
|||
39
hhhh
03.10.13
✎
09:29
|
(37) не, я не против. Просто товарищ сказал "длина в 32768 байт - это максимальное целое число в два байта", это ведь неправильно.
|
|||
40
Кирпич
03.10.13
✎
09:32
|
(39) ну да. товарищ зачем то знаки еще учитывает.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |