Как реализовать интерфейс с заданным заголовочным файлом? - PullRequest
0 голосов
/ 19 января 2019

Это, вероятно, глупый вопрос, и я не решался написать, но я новичок в ATL.

Мне нужно реализовать интерфейс в моем коде. У меня нет TLB или IDL для этого интерфейса, у меня просто есть файл заголовка.

Файл заголовка определяет интерфейс следующим образом:

EXTERN_C const IID IID_IExternalCon;
 ...    

     MIDL_INTERFACE("BCAC73A8-0226-4250-9D66-9656AA9BB86C")
        IExternalCon: public IUnknown
        {
        public:
            virtual HRESULT STDMETHODCALLTYPE GetName( 
                /* [in] */ __RPC__in ULONG *interface);
           //  ...

        }

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

Я сделал что-то вроде этого:

// is this a proper forward reference?
[
    object,
    uuid(BCAC73A8-0226-4250-9D66-9656AA9BB86C), // is this uuid supposed to match the one in the header?
    dual,
    nonextensible,
    pointer_default(unique)
]
interface IExternalCon: IUnknown
{
};


library ... {
    [
        uuid(d543911a-81b0-4de1-9511-d1f14caceed)
    ]

    // the class implementing my interface
    coclass ExternalConTest
    {
        [default] interface IExternalCon;
    };
}

Буду признателен за любую помощь, советы или рекомендации по работе с интерфейсами, основанными только на заголовочном файле.

Кстати, мой класс определяется следующим образом:

class ATL_NO_VTABLE CExternalConTest :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CExternalConTest, &CLSID_ExternalConTest>,
    public IExternalCon
{
public:
...

BEGIN_COM_MAP(CExternalConTest)
    COM_INTERFACE_ENTRY(IExternalCon)
    COM_INTERFACE_ENTRY(IUnknown)
END_COM_MAP()
..
}

1 Ответ

0 голосов
/ 19 января 2019

Для реализации внешнего интерфейса в объекте ATL необходимо сделать

  • добавить интерфейс в список реализованных интерфейсов (вы это сделали). Это изменит двоичное расположение класса (vtable и т. Д.)
  • добавить интерфейс в список BEGIN_COM_MAP. Это даст ATL, лежащему в основе реализации QueryInterface, положительный ответ на запросы для этого идентификатора интерфейса (вы это сделали). IUnknown здесь не нужно.
  • добавить объявление интерфейса в файл .h. Связи и аннотации там необязательны, я лично их удаляю. Я также всегда добавляю примечание с именем интерфейса, чтобы мы знали, какой метод используется каким интерфейсом. Когда у тебя много, это полезно ...
  • добавить реализацию интерфейса в файл .cpp.

Так что в вашем случае это будет для файла .h:

class ATL_NO_VTABLE CExternalConTest :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CExternalConTest, &CLSID_ExternalConTest>,
    public IExternalCon // change the class layout
{
public:
...

BEGIN_COM_MAP(CExternalConTest)
    COM_INTERFACE_ENTRY(IExternalCon) // answer to QueryInterface calls
END_COM_MAP()
...

public:
    // IExternalCon
    HRESULT GetName(ULONG *interface);
...
    // IWhatever
    HRESULT Blabla( ... );
    HRESULT Blabla2( ... );

...

и это для .cpp файла:

// CExternalConTest
...
// IExternalCon
HRESULT CExternalConTest::GetName(ULONG *interface)
{
    // TODO : implement this
    return S_OK;
}
...
// IWhatever
HRESULT CExternalConTest::Blabla(...)
{
    // TODO : implement this
    return S_OK;
}

HRESULT CExternalConTest::Blabla2(...)
{
    // TODO : implement this
    return S_OK;
}

Что касается .idl, вам не нужно ничего делать, потому что Visual Studio использует его в качестве основы для генерации кода. Обычно при использовании Visual Studio вы сначала изменяете .idl (используя мастера или нет), а затем заполняете пробелы.

...