DOC: The IDL Attribute "Implements" Is Not Documented (319981)



The information in this article applies to:

  • Microsoft Visual C++ .NET (2002)
  • Microsoft Visual C++ .NET (2003)

This article was previously published under Q319981

SUMMARY

There is no help topic about the IDL attribute implements. This attribute is new to Visual Studio .NET and is part of the C++ attribute programming support.

MORE INFORMATION

The IDL attribute implements applies to a coclass. The attribute specifies pseudo-interfaces and pseudo-dispinterfaces that are forced to be members of the IDL coclass.
[implements(interfaces={...}, dispinterfaces={...})]
				

The following sample code shows how to use this attibute:

Someidl.idl

//someidl.idl
import "docobj.idl";


[ version(1.0), uuid(0ed71801-a1b6-3178-af3b-9431fc00185e) ]
library odod
{
    importlib("stdole2.tlb");
    importlib("olepro32.dll");

    [
        object,
        uuid(1AECC9BB-2104-3723-98B8-7CC54722C7DD)
    ] 
    interface ISimple1 {
        [id(1)] HRESULT simple1();
    };
    [
        dual,
        uuid(1AECCABB-2104-3723-98B8-7CC54722C7DD)
    ] 
    interface ISimple2 {
        [id(1)] HRESULT simple2();
    };

    [
        uuid(1AECC9CC-2104-3723-98B8-7CC54722C7DD)
    ] 
    dispinterface ISna {
    properties:

    methods:
        [id(1)] HRESULT sna();
    };

    [
        uuid(159A9BBB-E5F1-33F6-BEF5-6CFAD7A5933F),
        version(1.0)
    ] 
    coclass CSimple {
        interface ISimple1;
        interface ISimple2;
        dispinterface ISna;
    };
}
				

Test.cpp

// test.cpp
#define _ATL_ATTRIBUTES 1
#include <atlbase.h>
#include <atlcom.h>
#include "someidl.h"    // IDL generated header that contains a definition
                        // of the pseudo-interface ISimple and pseudo-dispinterface ISna

[module(name = ralph)];

[dispinterface] __interface ITest {
    [id(0)] long x;
    [id(1)] HRESULT test();
};
    
[
	coclass,
	// Without this attribute, ISimple1, ISimple2, and ISna will not be in the
         // coclass in the generated IDL.
	implements(interfaces={ISimple1,ISimple2}, dispinterfaces=ISna)   
] 
class CTest : public ITest, 
	public ISimple1,
	public IDispatchImpl<ISimple2, &__uuidof(ISimple2)>, 
	public ISna
{
    long _x;
public:
    long get_x() { return _x; }
    void put_x(long x0) { _x = x0; }
    HRESULT test() { return S_OK; }
    HRESULT __stdcall simple1() { return S_OK; }
    HRESULT __stdcall simple2() { return S_OK; }
    HRESULT __stdcall sna() { return S_OK; }

    virtual HRESULT STDMETHODCALLTYPE ISna::Invoke(
                /* [in] */ DISPID dispIdMember,
                /* [in] */ REFIID riid,
                /* [in] */ LCID lcid,
                /* [in] */ WORD wFlags,
                /* [out][in] */ DISPPARAMS *pDispParams,
                /* [out] */ VARIANT *pVarResult,
                /* [out] */ EXCEPINFO *pExcepInfo,
                /* [out] */ UINT *puArgErr) 
    {
        HRESULT hr = S_OK;
        if (pDispParams == 0) {
            return DISP_E_BADVARTYPE;
        }
        if (pDispParams->cArgs > 0) {
            return DISP_E_BADPARAMCOUNT;
        }
        if (pVarResult != 0) {
            ::VariantInit(pVarResult);
        }
        switch (dispIdMember) {
        case 1:
            {
                if (pDispParams->cArgs != 0) {
                    return DISP_E_BADPARAMCOUNT;
                }
                hr = this->sna();
                break;
            }
        default:
            return DISP_E_MEMBERNOTFOUND;
        }
        return hr;
    }
    virtual HRESULT STDMETHODCALLTYPE ISna::GetIDsOfNames(
                /* [in] */ REFIID riid,
                /* [size_is][in] */ LPOLESTR *rgszNames,
                /* [in] */ UINT cNames,
                /* [in] */ LCID lcid,
                /* [size_is][out] */ DISPID *rgDispId) 
    {
        static LPOLESTR names[] = { L"sna" };
        static DISPID dids[] = { 1 };
        for (unsigned int i = 0; i < cNames; ++i) {
            int fFoundIt = 0;
            for (unsigned int j = 0; j < sizeof(names)/sizeof(LPOLESTR); ++j) {
                if (lstrcmpiW(rgszNames[i], names[j]) == 0) {
                    fFoundIt = 1;
                    rgDispId[i] = dids[j];
                    break;
                }
            }
            if (fFoundIt == 0) {
                return DISP_E_UNKNOWNNAME;
            }
        }
        return S_OK;
    }
    virtual HRESULT STDMETHODCALLTYPE ISna::GetTypeInfoCount(unsigned int*  pctinfo) 
    {
        if (pctinfo == NULL) {
            return E_POINTER;
        }
        CComPtr<ITypeInfo> spTypeInfo;
        *pctinfo = (SUCCEEDED(TypeInfoHelper(__uuidof(ISna), 0, &spTypeInfo))) ? 1 : 0;
        return S_OK;
    }
    virtual HRESULT STDMETHODCALLTYPE ISna::GetTypeInfo(unsigned int iTInfo,
                                                                  LCID lcid,
                                                                  ITypeInfo** ppTInfo) 
    {
        if (iTInfo != 0) {
            return DISP_E_BADINDEX;
        }
        return TypeInfoHelper(__uuidof(ISna), lcid, ppTInfo);
    }
    BEGIN_COM_MAP(CTest)
        COM_INTERFACE_ENTRY(ISimple1)
        COM_INTERFACE_ENTRY(ISimple2)
        COM_INTERFACE_ENTRY(ISna)
    END_COM_MAP()
};

				
Compile the previous files:
  1. midl /win32 /header "someidl.h" someidl.idl
  2. cl /LD test.cpp /link /idlout:output.idl
Then examine the generated IDL file (Output.idl). Note that ISimple1, ISimple2, and ISna are the members of the IDL coclass.

Output.idl

// output.idl
import "docobj.idl";
import "someidl.idl";


[ version(1.0), uuid(75faa99e-05ee-3988-ab92-8ef6bedda8e3) ]
library ralph
{
    importlib("stdole2.tlb");
    importlib("olepro32.dll");

    [
        uuid(1AECC9B3-2104-3723-98B8-7CC54722C7DD)
    ] 
    dispinterface ITest {
    properties:
        [id(0)] long x;

    methods:
        [id(1)] HRESULT  test();
    };

    [
        uuid(159A9B1A-E5F1-33F6-BEF5-6CFAD7A5933F),
        version(1.0)
    ] 
    coclass CTest {
        dispinterface ITest;
        interface ISimple1;
        interface ISimple2;
        dispinterface ISna;
    };
}
				
ITest is a COM interface that is defined in embedded IDL with the C++ keyword __interface. The compiler recognizes that ITest is a dispinterface, and then automatically generates implementations of methods such as IDispatch::Invoke and IDispatch::GetIDsOfNames, by using the specified dispids. In the generated IDL, the compiler places the dispinterface ITest as a member of the IDL coclass CTest.

ISimple1, ISimple2, and ISna do not appear in the coclass unless you use the implements attribute. The compiler considers pseudo-interfaces to be only structures, so it does not treat pseudo-interfaces in any special way. The user must provide all of the details of interface implementation. Also, the only way to get a pseudo-interface in the IDL coclass is by using the implements attribute.

The IDL attribute implements is defined as the following:
[
    define_attribute = "implements",
    argument_list = { interfaces, dispinterfaces },
    default_value("interfaces") = "",
    default_value("dispinterfaces") = "",
    help_string = "Specifies psudeo-(disp)interfaces that are forced to be members of the IDL coclass",
    usage = eCoClassUsage,
    group = eCompilerGroup,
    shipping = true,
    frequently_used = false,
    multivalue("interfaces") = true,
    multivalue("dispinterfaces") = true,
    repeatable = true,
];
				

Modification Type:MajorLast Reviewed:4/11/2003
Keywords:kbbug kbdocerr kbpending KB319981