Как вернуть из ActiveX-компонента структуру или массив?

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Ответить
Ivan093
Сообщения: 54
Зарегистрирован: 28 июн 2007, 13:59
Откуда: Екатеринбург
Контактная информация:

28 июн 2007, 14:17

Добрый день всем!
Пишу на билдере шестом компоненту ActiveX (будет использоваться в 1С 8.1). С горем пополам разобрался как ее создавать (литературы мало почему-то). Научился добавлять свои события, методы и свойства. Но возникла одна проблема: мне нужно возвращать в 1С структуру или массив, а в окне редактирования *.tlb файла при создании своего метода можно указать тип возвращаемого значения только как HRESULT. Подскажите, пожалуйста, как это можно сделать! Ну ооочень нужно :confused:
Absurd
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

28 июн 2007, 19:52

Все правильно - возвращаемое значение в COM/ActiveX используется для передачи ошибки или отсутствия таковой. Результаты работы функции возвращаются через [out,retval] параметры. Как правило это указатель на указатель на значение: [out,retval] MyType** myParam, т.е. вызывающий код тебе передает указатель на ячейку куда надо записать результат. Память вызывающий код будет чистить сам.
2B OR NOT(2B) = FF
Ivan093
Сообщения: 54
Зарегистрирован: 28 июн 2007, 13:59
Откуда: Екатеринбург
Контактная информация:

29 июн 2007, 08:05

Спасибо за пояснение! Т.е. как я понял вернуть массив любых значений (в том числе и структур), а так же структуру, все-таки можно. Это радует :)
Было бы совсем замечательно, если бы вы помогли с таким примером:
1. Завел свой метод getDbStat. Без входных параметров.
2. В параметрах указал Value с modifier [out, retval]. Какой мне Type
3. Он должен возвращать структуру вида: MapEvent, MapEventRegion, PositionCount. Все целые типа long.
4. Билдер создал в файле *_TLB.h описание метода
5. В файле *Impl.cpp он добавил следующий код:
Ivan093
Сообщения: 54
Зарегистрирован: 28 июн 2007, 13:59
Откуда: Екатеринбург
Контактная информация:

29 июн 2007, 08:09

Спасибо за пояснение! Т.е. как я понял вернуть массив любых значений (в том числе и структур), а так же структуру, все-таки можно. Это радует :)
Было бы совсем замечательно, если бы вы помогли с таким примером:
1. Завел свой метод getDbStat. Без входных параметров.
2. В параметрах указал Value с modifier [out, retval]. Какой мне Type выбрать (VARIANT*?)?
3. Он должен возвращать структуру вида: MapEvent, MapEventRegion, PositionCount. Все целые типа long.
4. Билдер создал в файле *_TLB.h описание метода
5. В файле *Impl.cpp он добавил следующий код:

STDMETHODIMP TMapScreenXImpl::getDbStat(VARIANT* Value)
{
try
{

}
catch(Exception &e)
{
return Error(e.Message.c_str(), IID_IMapScreenX);
}
return S_OK;
};

Как я понимаю в этом коде должно формироваться возвращаемое значение? Как его сформировать и вернуть?
Спасибо за помощь!!!
Ivan093
Сообщения: 54
Зарегистрирован: 28 июн 2007, 13:59
Откуда: Екатеринбург
Контактная информация:

29 июн 2007, 11:14

Все, всем спасибо, разобрался сам. :cool:
Владимир
Сообщения: 56
Зарегистрирован: 25 апр 2005, 13:57

29 июн 2007, 11:22

Если хочешь вернуть массив значений, то используй переменную типа SafeArray(безопасный массив), в которую помещай свои переменные типа long. Если захочешь передавать переменную пользовательского типа или типа не поддерживаемого автоматическим маршалингом, то тебе для передачи данных клиенту из твоей ActiveX придется самому написать код маршалинга с использованием интерфейса IMarshal или сгенерить dll-ки заместителя(proxy) и заглушки(stub).
Ivan093
Сообщения: 54
Зарегистрирован: 28 июн 2007, 13:59
Откуда: Екатеринбург
Контактная информация:

29 июн 2007, 11:56

Да уж... Как все непросто :)
Дело еще усугубилось тем, что эта компонента будет использоваться в 1с, а она, собака такая, не понимает возвращаемых структур, хотя тот же vbs (в Excel) понимает прекрасно. Надо будет что-то придумывать с ComSafeArray...
Absurd
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

29 июн 2007, 13:14

Ivan093 писал(а):Да уж... Как все непросто :)
Дело еще усугубилось тем, что эта компонента будет использоваться в 1с, а она, собака такая, не понимает возвращаемых структур, хотя тот же vbs (в Excel) понимает прекрасно. Надо будет что-то придумывать с ComSafeArray...
Я так понимаю, надо создать Automation OLE Object c методами типа GetMapEvent/SetMapEvent, GetMapEventRegion/SerMapEventRegion и передать его IDispatch через Variant значение.
2B OR NOT(2B) = FF
Ivan093
Сообщения: 54
Зарегистрирован: 28 июн 2007, 13:59
Откуда: Екатеринбург
Контактная информация:

29 июн 2007, 13:25

Ну, это как вариант. Но он подойдет для таких маленьких структур только. На самом деле, я привел просто вариант, дальше мне нужно будет возвращать структуры более сложные (больше 10 полей, причем разных типов) и массивы таких структур...
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

29 июн 2007, 15:28

Самый просто вариант для случая, когда нужно вернуть указатель на свою структуру - это создать ещё один COM объект, который поддерживает интерфейс, состоящий из набора пропертей. Причём каждый проперти соответствует полю из структуры. Имплементация обекта - тривиальна. Проперти привязывается к внутренней переменной - эхтим имплементация и ограничивается.

После этого метод, который должен возвращать структуру, изменяем так, чтобы он возвращал поинтер на только что созданный интерфейс нового объекта.

Если понадобиться возвращать массив из таких объектов, то нужно использовать SAFEARRAY из IUnknown поинтеров.

Вот и вся кухня.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить