ATL / COM II

Active Template Library.

 

Files in an ATL project:

ATL Object Wizard

COM

If IB inherits from IA, and you want to use the IA interface on IB don’t just cast IB to IA. Although the cast will often work, it will fail if proxy or stub code is involved. Instead, you should use QueryInterface to obtain a pointer to IA, e.g.:

hr = pIB->QueryInterface(IID_IA, &pIA);

Note: QueryInterface cannot be used to obtain an unrelated interface – you have to use CoCreateInstance again.

Tear-off Interfaces: Interfaces that defer initialisation until the last minute – typically to conserve limited resources (such as database connections)

 

IDL

One of the key things provided by IDL to COM is the marshalling information

Properties

To implement properties, we have to implement accessors (get) and/or mutators (set). Like methods, properties can be added through a wizard. Since internally properties are implemented as a get function and a set function, IDL needs to be specified for each function specified. Just to be difficult, because these are functions, we can add parameters to our properties if we wish!

Having added a property through the wizard, it’s easy to flesh out the generated methods get_PropertyName and put_PropertyName as these are exactly the same as any other “STDMETHODIMP” function.

However, referring to a property through C++ is not so straightforward. The wizard will have added an IDispatch and handler to the code for us so (after a bit of messing around) I was able to do this:

VARIANT var;

DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};

I->Invoke(5, IID_IFirst_ATL, NULL, DISPATCH_PROPERTYGET,

    &dispparamsNoArgs, &var, NULL, NULL);

std::cout << var.lVal << std::endl;


Where 5 happens to be the dispatch ID for the DaveTest property (as specified in the id(…) IDL attribute in the .IDL file:

[propget, id(5), helpstring("property DaveTest")]
    HRESULT DaveTest([out, retval] LONG* pVal);

[propput, id(5), helpstring("property DaveTest")]
    HRESULT DaveTest([in] LONG newVal);


The equivalent in C# to the above was: Console.WriteLine(x.DaveTest)

 

Smart Pointers