Jafar Kumarkiri


Hi,
I am newbie to COM technology,Since from begining I am not able to understand why there is need of double indirection in COM.
eg.
    HRESULT QueryInterface(
REFIID iid,
void ** ppvObject
);

Here is ,
void ** ppvObject can anybody explain me cause



Thanks.





Re: Visual C++ Language Why double indirection is used in COM ?

Giovanni Dicanio

Hi,

try to focus on the final goal: the goal is to have an output parameter to be written by QueryInterface.

Let's change context a bit, and consider how you would write a Swap function in C/C++, e.g.

void Swap( int x, int y ) // wrong

{

int temp;

temp = x;
x = y;

y = temp;

}

As you know, the above function is wrong, because it won't affect the values of x and y passed by the caller.

i.e.

If you write:

int a = 3;

int b = 5;

Swap(a, b);

// a still == 3

// b still == 5

The correct way to develop the aforementioned function is like so:

void Swap( int * x, int * y ) // OK : use pointers!

{

int temp;

temp = *x;
*x = *y;

*y = temp;

}

We use pointers, because x and y are [in, out] parameters, i.e. x and y are parameters whose values must be modified by the function, and the caller must use the modified values. If x and y were just [in] (i.e. input) parameters, passing by value would be just fine. But we need to pass "by reference", or "by pointer".

This is a general C/C++ rule: if you have some [in, out] parameter, you must pass it by pointer (i.e. add the * Smile

(Note: In C++ there are references, too - they are kind of "hidden pointers" - but COM tends to use pointers, because it is compatible also with C, and references are C++-only.)

So, come back to the COM world.

The purpose of QueryInterface is to return a pointer to a requested interface.

The C/C++ way of saying "generic pointer" is void *.

typedef void * GenericPointer;

If QueryInterface could return the interface generic pointer as return-value, the prototype would be like so:

GenericPointer QueryInterface( REFIID interfaceID );

i.e.

void * QueryInterface( REFIID interfaceID );

But QueryInterface has HRESULT as return value, so the "output" pointer to be returned is a parameter to the method (i.e. it goes into the argument list).

Now, think about Swap: when you want to modify a parameter in C/C++, you pass a *pointer* to the parameter.

So, the same is for QueryInterface:

HRESULT QueryInterface( REFIID id, GenericPointer p ); // wrong

would be useless, because 'p' is not written by the function (like Swap(int, int), without pointers); the correct form is:

HRESULT QueryInterface( REFIID id, GenericPointer * p ); // OK

like Swap( int *, int *)

Now, if you expand GenericPointer as void *, you get the double indirection:

HRESULT QueryInterface( REFIID, void * * p );

HTH,

Giovanni





Re: Visual C++ Language Why double indirection is used in COM ?

Brian Kramer

Long story short: QueryInterface returns two things: an HRESULT as a function result, and a pointer to the actual interface, whose address is passed into QueryInterface.

The interface's type is arbitrary, hence void*. The passing of the interface poiner (so you can receive its value) is that extra level of indirection.

eg.

IUnknown* pUnk;

if( SUCCEEDED( pSomeCOMObject->QueryInterface( IID_Unknown, &pUnk ))

// type of &pUnk is IUnknown**. C++ allows implicit conversion to void**.

{

}





Re: Visual C++ Language Why double indirection is used in COM ?

Jafar Kumarkiri


Thanks Giovanni Dicanio,

For your valuable explanation,that was very lucid and helpful.
Specially as you have shown comparision with normal swap() and COM's QueryInterface has left no room for doubt.

Thanks










Re: Visual C++ Language Why double indirection is used in COM ?

Giovanni Dicanio

Jafar: you're welcome.

Giovanni





Re: Visual C++ Language Why double indirection is used in COM ?

Sreedhar DVS

?**ppvObject C
C First Pointer points to Object and Second pointer points to the Interface





Re: Visual C++ Language Why double indirection is used in COM ?

Brian Kramer

The two asterisks are actually starry eyes meaning that ppvObject is uninitialized and needs coffee.