ATL/COM: определение интерфейса COM, который не будет доступен вне библиотеки DLL?
У меня есть библиотека на основе ATL/COM, созданная с использованием VC++ 6.0. Он используется для различных исполняемых файлов, созданных с использованием VB6.
Я хочу добавить некоторые COM-интерфейсы, которые не будут доступны через VB6, только для внутреннего использования DLL. Я хочу, чтобы они были интерфейсами COM, а не просто интерфейсами C++, потому что я буду использовать их на объектах, на которые у меня есть только ссылки на интерфейс COM (во время использования).
То есть я не знаю (во время использования), что этот указатель указывает на CFoo; Я просто знаю, что это указывает на IFoo, где IFoo является COM-интерфейсом, опубликованным так, чтобы VB6 знал об этом. Из этого указателя IFoo я хочу получить указатель IFooInternal, который будет реализовывать каждый класс, который реализует IFoo (не только CFoo). Более того, я не хочу, чтобы IFooInternal был доступен вне самой DLL; например, я не хочу, чтобы IFooInternal был доступен для VB6.
Любая помощь с этим будет принята с благодарностью. Предложения для альтернативных способов достижения той же общей цели также будут. Заранее спасибо.
2 ответа
Отвечая на мой собственный вопрос в пользу любого, кто найдет эту ветку в будущем. Однако, пожалуйста, обратите внимание, что я просто догадываюсь здесь, основываясь на экспериментах... кажется, это работает, по крайней мере, в моей конкретной ситуации, но я не знаю.
Во-первых, в некоторый соответствующий заголовочный файл (возможно, Hidden.h) поместите следующее, заменив недавно сгенерированный UUID на вновь сгенерированный UUID:
#ifndef __Hidden_h__
#define __Hidden_h__
extern "C" {
#ifndef __IHidden_FWD_DEFINED__
#define __IHidden_FWD_DEFINED__
typedef interface IHidden IHidden;
#endif // __IHidden_FWD_DEFINED__
#ifndef __IHidden_INTERFACE_DEFINED__
#define __IHidden_INTERFACE_DEFINED__
EXTERN_C const IID IID_IHidden;
MIDL_INTERFACE("a newly generated UUID")
IHidden : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE get_Something (
long __RPC_FAR *pVal ) = 0;
};
#endif // __IHidden_INTERFACE_DEFINED__
}
#endif // __Hidden_h__
Чтобы узнать, как определить другие типы параметров и тому подобное для функции, обратитесь к заголовку C++, который был сгенерирован MIDL из вашего файла IDL.
Затем, в заголовке для любого класса, который вы хотите реализовать этот интерфейс, добавьте интерфейс к объявлению класса:
class ATL_NO_VTABLE CBlah :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CBlah, &CLSID_CBlah>,
public ISupportErrorInfo,
public IConnectionPointContainerImpl<CBlah>,
public IBlah,
public IHidden
Также добавьте его в COM_MAP:
BEGIN_COM_MAP(CBlah)
COM_INTERFACE_ENTRY(IBlah)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
COM_INTERFACE_ENTRY(IHidden)
END_COM_MAP
И с этого момента это просто вопрос добавления стандартных объявлений C++ и определений функций интерфейса к классу:
public:
STDMETHOD(get_Something)(long *pVal);
(...)
STDMETHODIMP CBlah::get_Something(long *pVal)
{
if ( !pVal )
{
(error handling)
}
*pVal = 37;
return S_OK;
}
Я надеюсь, что это поможет кому-то в будущем. Я также надеюсь, что это не повредит мне, потому что это неправильно. Как я уже сказал, похоже, это работает.
Это не похоже на проблему, которая обязательно требует COM. Помните: если вы получаете неупорядоченное сообщение от COM, это просто нормально, а не какая-то волшебная COM-вещь. Итак, что вы можете сделать, это просто определить нормальный C++-интерфейс
IFooInternal
а затем dynamic_cast ваш
IFoo*
к тому, что.