Имя: Пароль:
1C
1С v8
Вопрос к гуру. Передача данных в 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) ну да. товарищ зачем то знаки еще учитывает.