![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Маршаллинг интерфейса.
Владислав © (2005-05-06 12:30:00)Здравствуйте.
Вот здесь:
http://www.rsdn.ru/Forum/Message.aspx?mid=1159650&only=1
я задал вопрос. Понятно, что на форуме по Delphi он не совсем уместен, но здесь тоже бывают люди, пишущие на MS VC.
Повторю его содержание:
Здравствуйте.
Проблема в следующем.
COM сервер реализован, как out-of-prosecc сервер (в EXE). В нем объявлен интерфейс:
// IServerList Interface
[
object,
uuid(297481F0-A3D2-43d1-B0DB-9A6C4B007885),
helpstring("IServerList Interface"),
pointer_default(unique)
]
interface IServerList : IUnknown{
[helpstring("method RegisterServer")] HRESULT RegisterServer([in] BSTR ConnStr, [out] LPDBOBJECTID ObjID, [out] IServer ** Server);
[helpstring("method UnregisterServer")] HRESULT UnregisterServer([in] LPDBOBJECTID ObjID);
[helpstring("method EnumServer")] HRESULT EnumServer([out] IEnumServer ** Enum);
};
При попытке вызова метода EnumServer получаю результат "интерфейс не реализован".
Сам интерфейс IEnumServer определен так:
// IEnumServer Interface
[
object,
uuid(D1019908-2CB3-4e71-9649-942750D0ED47),
helpstring("IEnumServer Interface"),
pointer_default(unique)
]
interface IEnumServer : IUnknown{
[helpstring("method Next")] HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] IServer ** rgelt , [out] ULONG * pceltFetched);
[helpstring("method Skip")] HRESULT Skip([in] ULONG celt);
[helpstring("method Reset")] HRESULT Reset(void);
[helpstring("method Clone")] HRESULT Clone([out] IEnumServer ** ppenum);
};
Класс для интерфейса IEnumServer реализован с помощью шаблонов вот так:
// Declaration of the CEnumServer
typedef _CopyInterface CServerCopy;
typedef CComEnum CEnumServer;//Class;
Возвращается энумератор так:
STDMETHODIMP CServerList::EnumServer(IEnumServer ** Enum)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr;
CComPtr iServer;
CCommonClass * cServer = NULL;
// Get pointer to IServer interface
hr = GetInterfaceFromClass(&iServer, &cServer);
if (FAILED(hr))
return hr;
IServer * serverIntf = (IServer *)iServer;
// Put pointer to IServer interface to enumerator
hr = CreateEnumerator(
(IUnknown**)Enum,
&serverIntf,
(&serverIntf + 1),
NULL,
AtlFlagCopy);
return hr;
}
Сервер корректно возвращает энумератор, но до клиента он (энумератор) не доходит.
Ну и еще дополнительная информация... При трассировке сервера, у него запрашиваются интерфейсы IMarshal и IStdMarshalInfo, на которые COM благополучно получает ответ "no implement". При этом proxy/stub зарегестрирована. Впрочем, сам интерфейс IServerList возвращается клиенту благополучно, и его первые два метода работают.
Подскажите пожалуйста, в каком направлении искать ошибку? Что я не так сделал?
Набережных С. (2005-05-06 21:22:00) [1]В [6] "вызываются" - читать "запрашиваются", в смысле вызывается QueryInterface с ихними IID. Все, спать пора:)
Набережных С. (2005-05-06 21:01:00) [2]
> Как показывает практика, не только для первого...
Какая-то неправильная практика:) Оба для каждого объекта вызываются только один раз, сразу после создания объекта, вкупе с некоторыми другими специальными. Если ответил отказом, то второго шанса не будет:)
Владислав (2005-05-06 19:17:00) [3]> Набережных С. © (06.05.05 18:33) [4]
Спасибо!
Дело ясное, что дело темное... На лицо явные пробелы в знаниях... Буду устранять...
"СОМ их запрашивает сразу после создания объекта перед созданием стандартного стаба для первогозапрошенного интерфейса
..."
Как показывает практика, не только для первого...
Больше всего мне Ваше "М-да..:)))" понравилось ;)
Набережных С. (2005-05-06 18:33:00) [4]
> Владислав © (06.05.05 17:05) [2]
> Я грешил, что с маршаллером проблемы, поэтому идет запрос
> этих интерфейсов.
Нет, не поэтому. Объект может реализовать эти интерфейсы, а может, как обычно и бывает, не реализовывать. СОМ их запрашивает сразу после создания объекта перед созданием стандартного стаба для первого запрошенного интерфейса, на случай, если объект сам намерен заняться маршалингом и создавать стаб не нужно(IMarshal), либо нужно создать "прокладку" между прокси и объектом(IStdMarshalInfo). Если оба ответа отрицательны, то дальше все идет обычным образом.
> Владислав © (06.05.05 17:30) [3]
М-да..:)))
Владислав (2005-05-06 17:30:00) [5]Спасибо!
Вопрос решился.
Ответ по ссылке в первом посте.
Владислав (2005-05-06 17:05:00) [6]"IServerList и IEnumServer в одном idl описаны?"
Сергей, IServerList и IEnumServer описаны в одном idl. Реализует эти объекты один сервер в экзешнике.
"Судя по тексту ошибки, наиболее вероятно, что проблемы с маршалингом IEnumServer по причине отсутствия Proxy/Stub для него. Посмотри в HCR\Interface, есть ли там этот интерфейс и кто там числится маршалером для него."
Конечно смотрел... Через oleview...
Там прописаны proxy/stub, которые я компилирую из стандартных файлов, генерируемых MIDL. И для IServerList и для IEnumServer в реестре прописана одна и та же библиотека proxy/stub dbsvrps.dll.
"Это стандартное поведение, не обращай внимания, в данном случае значения не имеет."
А вот это для меня новость, честно говоря. Я грешил, что с маршаллером проблемы, поэтому идет запрос этих интерфейсов. Я заблуждаюсь?
Так где копать причину неудачи? Может дать дополнительную информацию?
Набережных С. (2005-05-06 14:19:00) [7]
> у него запрашиваются интерфейсы IMarshal и IStdMarshalInfo
Это стандартное поведение, не обращай внимания, в данном случае значения не имеет.
Судя по тексту ошибки, наиболее вероятно, что проблемы с маршалингом IEnumServer по причине отсутствия Proxy/Stub для него. Посмотри в HCR\Interface, есть ли там этот интерфейс и кто там числится маршалером для него. IServerList и IEnumServer в одном idl описаны?