Domanda

I am reading a COM sample at http://msdn.microsoft.com/en-us/library/windows/desktop/dd389098(v=vs.85).aspx

I really cannot comprehend (void **) in

hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);

So I have tried some values returned by different types of pointers by the class

class Point{
private:
    int x, y;
public:
    Point(int inputX, int inputY){x = inputX, y = inputY;}
    int getX(){return x;}
    int getY(){return y;}
    friend ostream& operator << (ostream &out, Point &cPoint);
    Point operator-(){
        return Point(-x, -y);
    }
};

ostream& operator << (ostream &out, Point &cPoint){
    return out<< "(" << cPoint.x << ", " << cPoint.y << ")";
}

and printing out

Point *p = new Point(1,2);
cout << p << endl << &p << endl << endl
<< *&p << endl<< **&p << endl<<endl 
<< (void *) &p << endl << (void **) &p ;

(void*) really has no difference with (void **). What does (void **)&pControl want to return?

È stato utile?

Soluzione

hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);

What does (void **)&pControl want to return?

QueryInterface() is one of the three methods of IUnknown, which is the base root interface of all COM interfaces.

The MSDN documentation for IUnknown::QueryInterface() clearly states that:

HRESULT QueryInterface(
  [in]   REFIID riid,
  [out]  void **ppvObject
);

ppvObject [out] The address of a pointer variable that receives the interface pointer requested in the riid parameter. Upon successful return, *ppvObject contains the requested interface pointer to the object. If the object does not support the interface, *ppvObject is set to NULL.

So, in your particular case, upon successful return, pControl will contain the requested pointer to the IMediaControl interface, as specified in your function call via the first argument IID_IMediaControl.


Now, let's try to better understand why the double pointer indirection: void**.

void* means "pointer to anything".

So, one might think: "Why isn't the second parameter of QueryInterface() just a void*?"

The problem is that this parameter is an output parameter. This means that QueryInterface() will write something into that parameter, for the caller to use it.

And, in C (and COM has several C-isms), when you have an output parameter, you must use a pointer (*).
(Note In C++ you can also use a reference &.)

So, in this case we have the first level of indirection of void* that means "pointer to anything".
And the second level of indirection (the other *), that means: "This is an output parameter".

You can think of it also in this way:

typedef void* PointerToAnything;

HRESULT QueryInterface(..., /* [out] */ PointerToAnything* pSomeInterface);

// pSomeInterface is an output parameter.
//
// [out] --> use * (pointer), 
// so it's 'PointerToAnything*' (not just 'PointerToAnything'),
// so, with proper substitution, it's 'void**' (not just 'void*').
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top