Имеется СОМ-сервер (dll). В нем — 2 интерфейса: IManager и IDevice.
Интерфейс IManager имеет один метод — GetDevice (NumDevice), который возвращет клиенту интерфейс IDevice. Дальнейшая работа клиента происходи именно с интерфейсом IDevice. Использовать СОМ предполагается в основном в VBA (MS Access) примерно вот так:
Dim manager as Manager
dim device1 as device
dim device2 as device
set manager = new Manager
set device1 = manager.GetDevice (1)
set device2 = manager.GetDevice (2)
.....
device1.Metod1 (для первого устройства)
device2.Metod1 (для второго устройства)
.....
set device1 = nothing
set device2 = nothing
set manager = nothing
Вопрос следующий: Как реализовать метод GetDevice (NumDevice), чтобы он возворащал один интерфейс, но фактически к разным устройствам?
Здравствуйте, asg, Вы писали:
asg>Доброе время суток!
asg>Имеется СОМ-сервер (dll). В нем — 2 интерфейса: IManager и IDevice. asg>Интерфейс IManager имеет один метод — GetDevice (NumDevice), который возвращет клиенту интерфейс IDevice. Дальнейшая работа клиента происходи именно с интерфейсом IDevice. Использовать СОМ предполагается в основном в VBA (MS Access) примерно вот так: asg>Dim manager as Manager asg>dim device1 as device asg>dim device2 as device
asg>set manager = new Manager asg>set device1 = manager.GetDevice (1) asg>set device2 = manager.GetDevice (2) asg>..... asg>device1.Metod1 (для первого устройства)
asg>device2.Metod1 (для второго устройства) asg>..... asg>set device1 = nothing asg>set device2 = nothing asg>set manager = nothing
asg>Вопрос следующий: Как реализовать метод GetDevice (NumDevice), чтобы он возворащал один интерфейс, но фактически к разным устройствам?
Не понял вопроса. Он же и так возвращает один интерфейс IDevice? Или ты хочешь указывать к какому устройству возвращать интерфейс, те конкретную имплементацию IDevice? Или ты хочешь чтобы GetDevice мог возвращать разные интерфейсы? Для первого случая достаточно в метод GetDevice добавить параметр, указывающий на реализацию этого интерфейса — CLSID. Для второго можно возвращать IUnknown а потом кверить нужный интерфейс.
Здравствуйте, asg, Вы писали:
asg>Доброе время суток!
asg>Имеется СОМ-сервер (dll). В нем — 2 интерфейса: IManager и IDevice.
В COM-сервере должно быть 2 СОМ-объекта: один реализует IManager, другой — IDevice. Клиент может запросить по clsid только первый, второй создаётся через метод первого.
asg>Вопрос следующий: Как реализовать метод GetDevice (NumDevice), чтобы он возворащал один интерфейс, но фактически к разным устройствам?
В этом методе создаётся объект, реализующий IDevice. При создании этого объекта, ему можно передать параметр — NumDevice. Дальше уже сам этот созданный объект будет иметь номер своего девайса и работать только с ним. Это если логика работы с одним девайсом такая же как и с любым другим. Если логика работы разная, то... но мне кажется тут именно первый случай, да?
КЛ>Не понял вопроса. Он же и так возвращает один интерфейс IDevice? Или ты хочешь указывать к какому устройству возвращать интерфейс, те конкретную имплементацию IDevice? Или ты хочешь чтобы GetDevice мог возвращать разные интерфейсы? Для первого случая достаточно в метод GetDevice добавить параметр, указывающий на реализацию этого интерфейса — CLSID. Для второго можно возвращать IUnknown а потом кверить нужный интерфейс.
Уточню вопрос. Предположим, что IDevice — интерфейс для работы с модемом. В системе установлено два модема. Хотелось бы, чтобы GetDevice(NumDevice) — возвращал интерфейс для работы с конкретным устройством.
Dim manager as Manager
dim device1 as device
dim device2 as device
set manager = new Manager
set device1 = manager.GetDevice (1) — первый модем
set device2 = manager.GetDevice (2) — второй модем
.....
device1.Metod1 (для первого устройства)
device2.Metod1 (для второго устройства)
.....
set device1 = nothing
set device2 = nothing
set manager = nothing
Можно ли это сделать? или есть какой-нибудь другой (более простой) способ реализации этой идеи?
>Клиент может запросить по clsid только первый, второй создаётся через метод первого.
А можно пример, как создать второй СОМ-объект, который реализует IDevice. И еще вопрос, можно ли сделать так, чтобы пользователь мог получить интерфейс к устройсву только через вызов метода GetDevice (NumDevice) ?
>Это если логика работы с одним девайсом такая же как и с любым другим.
Вы правы, логика работы с одним устройством такая же как и с любым другим.
Здравствуйте, asg, Вы писали:
>>Клиент может запросить по clsid только первый, второй создаётся через метод первого.
asg>А можно пример, как создать второй СОМ-объект, который реализует IDevice.
примерно так:
. Там и примеры скачать можно. Поиск по форуму тоже, кстати, работает
asg>И еще вопрос, можно ли сделать так, чтобы пользователь мог получить интерфейс к устройсву только через вызов метода GetDevice (NumDevice) ?
да, просто не регистрировать объект, который реализует IDevice.
Здравствуйте, asg, Вы писали:
asg>А можно пример, как создать второй СОМ-объект, который реализует IDevice. И еще вопрос, можно ли сделать так, чтобы пользователь мог получить интерфейс к устройсву только через вызов метода GetDevice (NumDevice) ?
А уже инстанс С++ класса CComObject<CMyDevice> нужно связывать (через дата-мемберы, например) c теми или иными физическими девайсами.
asg>>И еще вопрос, можно ли сделать так, чтобы пользователь мог получить интерфейс к устройсву только через вызов метода GetDevice (NumDevice) ? М>да, просто не регистрировать объект, который реализует IDevice.
Здравствуйте, algol, Вы писали: A>Макрос OBJECT_ENTRY_NON_CREATEABLE:
A>
A>BEGIN_OBJECT_MAP(ObjectMap)
A>OBJECT_ENTRY(CLSID_MANAGER, CManager)
A>OBJECT_ENTRY_NON_CREATEABLE(CDevice)
A>END_OBJECT_MAP()
A>
При использовании этого макроса при получении интрефейса (set dev1 = manager.GetDevice(1)) возникает ошибка: run-Time Error/ 80004005 Metod 'GetDevice' of object 'IManager' failed.
код метода GetDevice
STDMETHODIMP TManagerImpl::GetDevice(IDevice** Device)
{
IUnknown *pUnk;
Здравствуйте, asg, Вы писали:
asg>Здравствуйте, Константин Л., Вы писали:
КЛ>>Здравствуйте, asg, Вы писали:
КЛ>>CoInitialize тут абсолютно лишний
asg>Я это понял, и потому поставил комментарий
При использовании этого макроса при получении интрефейса (set dev1 = manager.GetDevice(1)) возникает ошибка: run-Time Error/ 80004005 Metod 'GetDevice' of object 'IManager' failed.
подскажите, как нужно создавать инстанс, чтобы клиент не мог на прямую создать объект Device, а только через вызов метода GetDevice? Макрос OBJECT_ENTRY_NON_CREATEABLE — не помогает.
Здравствуйте, asg, Вы писали:
asg>подскажите, как нужно создавать инстанс, чтобы клиент не мог на прямую создать объект Device, а только через вызов метода GetDevice? Макрос OBJECT_ENTRY_NON_CREATEABLE — не помогает.
Так вам уже писали, создавайте объект так:
CComObject<CMyDevice>* m_myDevice;
HRESULT hr = ATL::CComObject<CMyDevice>::CreateInstance(&m_myDevice);
// Инициализируете объект вызовом метода или установкой свойств,
// не объявленных в COM интерфейсе
m_myDevice->Init(...);
Можно еще почитать Q181265 "HOWTO: Create ATL COM Objects".
А создание через ::CoCreateInstance() — это как раз то, что мы запретили.