class CNetReader: IDispatchImpl<INetReader>, public IReader;
class CPortReader: IDispatchImpl<IPortReader>, public IReader;
class CMyTest DispImpl<IMyTest>
{
IReader* m_pReader
public:
void Bind(IReader* pReader){m_pReader = pReader;};
void Test(){m_pReader->Read(...);};
};
Идея понятна, есть класс CMyTest, который может работать через разный транспорт. С реализацией не получается. Необходимо, что бы клиенское приложение можно было написать на VBA, VB, VBScript, Perl ну и C++ естественно.
Если пишу так как указано выше — ругается перл. Он не понимает не-dispatch инетрфейсов (в данном случае iReader). Если передаю как IUnknown IDispatch или VARIANT не работает VBA по совершенно непонятной причине. Замучался уже, время жалко тратить на изучение всего этого добра, поможите кто может.
Здравствуйте, LelicDsp, Вы писали:
LD>Вот вопрос от не большого знатока ATL/COM. LD>Есть интерфейсы скажем LD>[midl] LD>interface IReader : IUnknown LD>{ LD> void Read(BSTR* pStr); LD>};
а почему бы тебе не наследовать от IDispatch?
Здравствуйте, SaloS, Вы писали:
SS>Здравствуйте, LelicDsp, Вы писали:
LD>>Вот вопрос от не большого знатока ATL/COM. LD>>Есть интерфейсы скажем LD>>[midl] LD>>interface IReader : IUnknown LD>>{ LD>> void Read(BSTR* pStr); LD>>}; SS>а почему бы тебе не наследовать от IDispatch?
Если я правильно понимаю, то только один из реализуемых интерфейсов может быть Dispatch. Соответственно, если уменя есть класс CNetReader то он реализует дуальный интерфейс INetReader, а IReader должен быть обычным. Хотя я пробовал и такой вариант.
Здравствуйте, Кодёнок, Вы писали:
Кё>Соглашения OLE Automation требуют, чтобы все методы возвращали HRESULT. Может поэтому VBA не работает?
Да нет, это конечно не причем. И метод, HRESULT, я текст по памяти просто воспроизводил. Вот полный IDL:
class ATL_NO_VTABLE CComPort :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CComPort, &CLSID_ComPort>,
public ISupportErrorInfo,
public IConnectionPointContainerImpl<CComPort>,
public IDispatchImpl<IComPort, &IID_IComPort, &LIBID_MTLib>,
public IReader
{
///
}
Насколько я полнял твою проблему (не уверен что до конца, в первом сообщении у тебя одни классы, в IDL — другие, и не совсем понятно кто из них как должен друг с другом взаимодействовать) — тебе нужно наследовать IReader от IDispatch, INetReader и IPortReader — от IReader.
Здравствуйте, Left2, Вы писали:
L>Насколько я полнял твою проблему (не уверен что до конца, в первом сообщении у тебя одни классы, в IDL — другие, и не совсем понятно кто из них как должен друг с другом взаимодействовать) — тебе нужно наследовать IReader от IDispatch, INetReader и IPortReader — от IReader.
Классы разные, т.к. вчера писал по памяти и очень быстро, просто сильно достало сидеть и разбираться в мелкософтских ограничениях.
Предлагаемое тобой решение это как раз то, что было сделано с самого начала. Не работает. роблема в том, что нельзя имплементировать болеее одного Dispatch интерфейса. Точнее имплементировать можно, но виден будет только [default]. Спасибо MS, испоганили хорошую идею. Полный маразм, какой смысл вообще в абстрактных интерфейсах, если реально один класс = один интерфейс.
Здравствуйте, LelicDsp, Вы писали:
LD>Здравствуйте, Left2, Вы писали:
L>>Насколько я полнял твою проблему (не уверен что до конца, в первом сообщении у тебя одни классы, в IDL — другие, и не совсем понятно кто из них как должен друг с другом взаимодействовать) — тебе нужно наследовать IReader от IDispatch, INetReader и IPortReader — от IReader.
LD>Классы разные, т.к. вчера писал по памяти и очень быстро, просто сильно достало сидеть и разбираться в мелкософтских ограничениях.
LD>Предлагаемое тобой решение это как раз то, что было сделано с самого начала. Не работает.
Поясню что не работает. При работе из perl (VBS вероятно, тоже) вываливаемся с ошибкой про несовместимыен типы. Как Я понимаю ее происхождение: скажем CComPort реализует IComPort & IReader, оба IDispatch. Когда вызывается CSimpleTester.Bind с указателем на инстанцию CComPort код маршалинга решает в рантайме проверить что за класс ему передали, желая убедиться, что это IReader, а делает он это через IDispatch. А IDispatch он получает от [default] интерфейса сиречь IComPort. Соответственно, при проверке типов он вылетает c ошибкой, т.к. не находит ожидаемого интерфейса IReader.
Вообще жто мои догадки, т.к. я не знаю как работает маршалинг при передаче Dispatch интерфейсов, но из получается, что именно так он и работает.
Погоди на MS грешить
У тебя и будет 1 Idispatch-унаследованый интерфейс в классе — IPortReader или INetReader
Имплементацию Ireader выносишь в шаблонный класс IreaderImpl
class ATL_NO_VTABLE CComPortReader :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CComPort, &CLSID_ComPort>,
public ISupportErrorInfo,
public IConnectionPointContainerImpl<CComPort>,
public IDispatchImpl<IreaderImpl<IPortReader >, &IID_IPortReader, &LIBID_MTLib>,
{
///
}
В карте интерфейсов выставляешь 3 интерфейса — IPortReader, Ireader и IDispatch
Это вообщем-то стандартное решение для имплементации интерфейсов, унаследованных от наследников Idispatch — порывшись по форуму найдёшь немало таких примеров
Здравствуйте, Left2, Вы писали:
L>В карте интерфейсов выставляешь 3 интерфейса — IPortReader, Ireader и IDispatch
L>Это вообщем-то стандартное решение для имплементации интерфейсов, унаследованных от наследников Idispatch — порывшись по форуму найдёшь немало таких примеров
Спасибо большое, вот это уже что-то реальное, буду пробовать!
Хотя пока и не въехал
Здравствуйте, LelicDsp, Вы писали:
LD>Идея понятна, есть класс CMyTest, который может работать через разный транспорт. С реализацией не получается. Необходимо, что бы клиенское приложение можно было написать на VBA, VB, VBScript, Perl ну и C++ естественно.
Я так понимаю, что у тебя в клиенте есть экземпляры-коклассов CMyTest, CNetReader и/или CPortReader, один из которых ты передаешь экземпляру CMyTest для какой-то работы. Так что все твои умеющие работать с dispatch интерфейсами клиенты имеют правильные и понятные им указатели. И передаче экземпляра CXxxReader-а в экземпляр CMyTest они попытаются передать то, что имеют.
Поэтому правильно специфицировать метод Bind так, как ты сделал в IDL файле
PS
Единственное, что можно еще заметить, — IReader не является OLE-совместимым и требует прокси DLL для маршаллинга. Поставь ключевое слово oleautomation в определение IReader:
Проверялось, в таком виде работает из perl, не работает из VBA.
Vi2>Единственное, что можно еще заметить, — IReader не является OLE-совместимым и требует прокси DLL для маршаллинга. Поставь ключевое слово oleautomation в определение IReader:
Здравствуйте, Vi2, Вы писали:
Vi2>Единственное, что можно еще заметить, — IReader не является OLE-совместимым и требует прокси DLL для маршаллинга. Поставь ключевое слово oleautomation в определение IReader:
Спасибо, помогло вроде. По крайней мере тестовые проекты на VB, VBA и perl работают. Единственное что при сборке компилятор начал ругаться на InlineIsEqualGUID — пришлось заменить на IsEqualGUID. В чем тут могут быть грабли?
LD>Предлагаемое тобой решение это как раз то, что было сделано с самого начала. Не работает. роблема в том, что нельзя имплементировать болеее одного Dispatch интерфейса. Точнее имплементировать можно, но виден будет только [default]. Спасибо MS, испоганили хорошую идею. Полный маразм, какой смысл вообще в абстрактных интерфейсах, если реально один класс = один интерфейс.