ATL / COM: определение интерфейса COM, который не будет доступен вне библиотеки DLL? - PullRequest
1 голос
/ 01 октября 2009

У меня есть библиотека на основе 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.

Любая помощь с этим будет принята с благодарностью. Предложения по альтернативным способам достижения той же общей цели также будут. Заранее спасибо.

1 Ответ

2 голосов
/ 02 октября 2009

Отвечая на мой собственный вопрос в интересах любого, кто найдет эту ветку в будущем. Однако, пожалуйста, обратите внимание, что я просто догадываюсь здесь, основываясь на экспериментах ... кажется, это работает, по крайней мере, в моей конкретной ситуации, но я не знаю.

Во-первых, в некоторый соответствующий заголовочный файл (возможно, 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;
}

Надеюсь, это поможет кому-то в будущем. Я также надеюсь, что это не повредит мне, потому что это неправильно. Как я уже сказал, похоже, это работает.

...