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:
- midl /win32 /header "someidl.h" someidl.idl
- 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,
];