Страница 1 из 7

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

Добавлено: 28 июн 2007, 14:17
Ivan093
Добрый день всем!
Пишу на билдере шестом компоненту ActiveX (будет использоваться в 1С 8.1). С горем пополам разобрался как ее создавать (литературы мало почему-то). Научился добавлять свои события, методы и свойства. Но возникла одна проблема: мне нужно возвращать в 1С структуру или массив, а в окне редактирования *.tlb файла при создании своего метода можно указать тип возвращаемого значения только как HRESULT. Подскажите, пожалуйста, как это можно сделать! Ну ооочень нужно :confused:

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

Добавлено: 28 июн 2007, 19:52
Absurd
Все правильно - возвращаемое значение в COM/ActiveX используется для передачи ошибки или отсутствия таковой. Результаты работы функции возвращаются через [out,retval] параметры. Как правило это указатель на указатель на значение: [out,retval] MyType** myParam, т.е. вызывающий код тебе передает указатель на ячейку куда надо записать результат. Память вызывающий код будет чистить сам.

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

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

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

Добавлено: 29 июн 2007, 08:09
Ivan093
Спасибо за пояснение! Т.е. как я понял вернуть массив любых значений (в том числе и структур), а так же структуру, все-таки можно. Это радует :)
Было бы совсем замечательно, если бы вы помогли с таким примером:
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;
};

Как я понимаю в этом коде должно формироваться возвращаемое значение? Как его сформировать и вернуть?
Спасибо за помощь!!!

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

Добавлено: 29 июн 2007, 11:14
Ivan093
Все, всем спасибо, разобрался сам. :cool:

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

Добавлено: 29 июн 2007, 11:22
Владимир
Если хочешь вернуть массив значений, то используй переменную типа SafeArray(безопасный массив), в которую помещай свои переменные типа long. Если захочешь передавать переменную пользовательского типа или типа не поддерживаемого автоматическим маршалингом, то тебе для передачи данных клиенту из твоей ActiveX придется самому написать код маршалинга с использованием интерфейса IMarshal или сгенерить dll-ки заместителя(proxy) и заглушки(stub).

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

Добавлено: 29 июн 2007, 11:56
Ivan093
Да уж... Как все непросто :)
Дело еще усугубилось тем, что эта компонента будет использоваться в 1с, а она, собака такая, не понимает возвращаемых структур, хотя тот же vbs (в Excel) понимает прекрасно. Надо будет что-то придумывать с ComSafeArray...

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

Добавлено: 29 июн 2007, 13:14
Absurd
Ivan093 писал(а):Да уж... Как все непросто :)
Дело еще усугубилось тем, что эта компонента будет использоваться в 1с, а она, собака такая, не понимает возвращаемых структур, хотя тот же vbs (в Excel) понимает прекрасно. Надо будет что-то придумывать с ComSafeArray...
Я так понимаю, надо создать Automation OLE Object c методами типа GetMapEvent/SetMapEvent, GetMapEventRegion/SerMapEventRegion и передать его IDispatch через Variant значение.

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

Добавлено: 29 июн 2007, 13:25
Ivan093
Ну, это как вариант. Но он подойдет для таких маленьких структур только. На самом деле, я привел просто вариант, дальше мне нужно будет возвращать структуры более сложные (больше 10 полей, причем разных типов) и массивы таких структур...

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

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

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

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

Вот и вся кухня.