Возрат интерфейса из СОМ-сервера
От: asg Россия  
Дата: 04.07.06 02:46
Оценка:
Доброе время суток!

Имеется СОМ-сервер (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), чтобы он возворащал один интерфейс, но фактически к разным устройствам?
Re: Возрат интерфейса из СОМ-сервера
От: Константин Л.  
Дата: 04.07.06 06:00
Оценка:
Здравствуйте, 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 а потом кверить нужный интерфейс.
Re: Возрат интерфейса из СОМ-сервера
От: Максим2006 Беларусь  
Дата: 04.07.06 06:57
Оценка:
Здравствуйте, asg, Вы писали:

asg>Доброе время суток!


asg>Имеется СОМ-сервер (dll). В нем — 2 интерфейса: IManager и IDevice.

В COM-сервере должно быть 2 СОМ-объекта: один реализует IManager, другой — IDevice. Клиент может запросить по clsid только первый, второй создаётся через метод первого.

asg>Вопрос следующий: Как реализовать метод GetDevice (NumDevice), чтобы он возворащал один интерфейс, но фактически к разным устройствам?

В этом методе создаётся объект, реализующий IDevice. При создании этого объекта, ему можно передать параметр — NumDevice. Дальше уже сам этот созданный объект будет иметь номер своего девайса и работать только с ним. Это если логика работы с одним девайсом такая же как и с любым другим. Если логика работы разная, то... но мне кажется тут именно первый случай, да?
Re[2]: Возрат интерфейса из СОМ-сервера
От: asg Россия  
Дата: 04.07.06 07:04
Оценка:
Здравствуйте, Константин Л., Вы писали:


КЛ>Не понял вопроса. Он же и так возвращает один интерфейс 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

Можно ли это сделать? или есть какой-нибудь другой (более простой) способ реализации этой идеи?
Re[2]: Возрат интерфейса из СОМ-сервера
От: asg Россия  
Дата: 04.07.06 07:20
Оценка:
>Клиент может запросить по clsid только первый, второй создаётся через метод первого.

А можно пример, как создать второй СОМ-объект, который реализует IDevice. И еще вопрос, можно ли сделать так, чтобы пользователь мог получить интерфейс к устройсву только через вызов метода GetDevice (NumDevice) ?

>Это если логика работы с одним девайсом такая же как и с любым другим.


Вы правы, логика работы с одним устройством такая же как и с любым другим.
Re[3]: Возрат интерфейса из СОМ-сервера
От: Максим2006 Беларусь  
Дата: 04.07.06 08:12
Оценка: 5 (1)
Здравствуйте, asg, Вы писали:

>>Клиент может запросить по clsid только первый, второй создаётся через метод первого.


asg>А можно пример, как создать второй СОМ-объект, который реализует IDevice.

примерно так:
HRESULT hr = ATL::CComObject<CMyDevice>::CreateInstance(...);


посмотри тут
Автор(ы): Том Армстронг

В этой главе, позаимствованной из книги "ActiveX-Создание Web-приложений"
Тома Армстронга, рассматриваются основные понятия модели COM, такие как
интерфейс IUnknown, GUID, фабрики классов и т. д. Кроме того, автор приводит
примеры реализации COM-клиентов и COM-серверов с использованием языка C++,
Visual Basic и библиотеки ATL.
. Там и примеры скачать можно. Поиск по форуму тоже, кстати, работает


asg>И еще вопрос, можно ли сделать так, чтобы пользователь мог получить интерфейс к устройсву только через вызов метода GetDevice (NumDevice) ?

да, просто не регистрировать объект, который реализует IDevice.
Re[4]: Возрат интерфейса из СОМ-сервера
От: asg Россия  
Дата: 04.07.06 08:30
Оценка:
Здравствуйте, Максим2006, Вы писали:

Благодарю за помощь. Буду пробовать.
Re[3]: Возрат интерфейса из СОМ-сервера
От: algol Россия about:blank
Дата: 04.07.06 12:19
Оценка:
Здравствуйте, asg, Вы писали:

asg>А можно пример, как создать второй СОМ-объект, который реализует IDevice. И еще вопрос, можно ли сделать так, чтобы пользователь мог получить интерфейс к устройсву только через вызов метода GetDevice (NumDevice) ?


Макрос OBJECT_ENTRY_NON_CREATEABLE:

BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_MANAGER, CManager)
OBJECT_ENTRY_NON_CREATEABLE(CDevice)
END_OBJECT_MAP()
Re[4]: Возрат интерфейса из СОМ-сервера
От: George Seryakov Россия  
Дата: 04.07.06 15:49
Оценка: +1
Здравствуйте, Максим2006, Вы писали:

М>примерно так:

М>
М>HRESULT hr = ATL::CComObject<CMyDevice>::CreateInstance(...);
М>


А уже инстанс С++ класса CComObject<CMyDevice> нужно связывать (через дата-мемберы, например) c теми или иными физическими девайсами.

asg>>И еще вопрос, можно ли сделать так, чтобы пользователь мог получить интерфейс к устройсву только через вызов метода GetDevice (NumDevice) ?

М>да, просто не регистрировать объект, который реализует IDevice.

Кокласс, имеется в виду.
GS
Re[4]: Возрат интерфейса из СОМ-сервера
От: asg Россия  
Дата: 05.07.06 01:51
Оценка:
Здравствуйте, 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;

try
{
HRESULT hr;
// ::CoInitialize (NULL);
hr = ::CoCreateInstance (CLSID_Device,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDevice,
(void **)&pUnk);

if (SUCCEEDED ( hr ))
{
MessageBox (NULL, "Объект создан успешно", "GetDevice", MB_OK);
hr = pUnk->QueryInterface(IID_IDevice, (void**)Device);
if (SUCCEEDED (hr))
{
MessageBox (NULL, "Запрос интерфейса — успешен", "GetDevice", MB_OK);
pUnk->Release();
}
else
{
MessageBox (NULL, "Ошибка запроса интерфейса", "GetDevice", MB_OK);
return E_FAIL;
}
}
else
{
MessageBox (NULL, "Ошибка создания объекта", "GetDevice", MB_OK);
return E_FAIL;
}
}
catch(Exception &e)
{
return Error(e.Message.c_str(), IID_IDevice);
}
return S_OK;
}
Re[5]: Возрат интерфейса из СОМ-сервера
От: Константин Л.  
Дата: 06.07.06 16:52
Оценка:
Здравствуйте, asg, Вы писали:

CoInitialize тут абсолютно лишний
Re[6]: Возрат интерфейса из СОМ-сервера
От: asg Россия  
Дата: 07.07.06 01:37
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Здравствуйте, asg, Вы писали:


КЛ>CoInitialize тут абсолютно лишний


Я это понял, и потому поставил комментарий
Re[7]: Возрат интерфейса из СОМ-сервера
От: Константин Л.  
Дата: 07.07.06 08:41
Оценка:
Здравствуйте, asg, Вы писали:

asg>Здравствуйте, Константин Л., Вы писали:


КЛ>>Здравствуйте, asg, Вы писали:


КЛ>>CoInitialize тут абсолютно лишний


asg>Я это понял, и потому поставил комментарий


сорри, не заметил, код надо форматировать
Re[8]: Возрат интерфейса из СОМ-сервера
От: asg Россия  
Дата: 07.07.06 09:18
Оценка:
Здравствуйте, Константин Л., Вы писали:

Виноват, исправлюсь
Но вопрос все-таки открытый

BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_MANAGER, CManager)
OBJECT_ENTRY_NON_CREATEABLE(CDevice)
END_OBJECT_MAP()

При использовании этого макроса при получении интрефейса (set dev1 = manager.GetDevice(1)) возникает ошибка: run-Time Error/ 80004005 Metod 'GetDevice' of object 'IManager' failed.

подскажите, как нужно создавать инстанс, чтобы клиент не мог на прямую создать объект Device, а только через вызов метода GetDevice? Макрос OBJECT_ENTRY_NON_CREATEABLE — не помогает.
Re[9]: Возрат интерфейса из СОМ-сервера
От: algol Россия about:blank
Дата: 07.07.06 10:58
Оценка:
Здравствуйте, 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() — это как раз то, что мы запретили.
Re[10]: Возрат интерфейса из СОМ-сервера
От: asg Россия  
Дата: 10.07.06 02:17
Оценка:
Огромное спасибо за помощь!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.