Click here to Skip to main content
15,890,512 members
Please Sign up or sign in to vote.
2.50/5 (2 votes)
See more:
Hi to everyone!

I've been trying to find an answer to this question, but couldn't find it. I have been reading a lot of articles about COM programming but I still don't understand one very specific issue about pointers.

I understand that in COM programming you should query for specific interfaces in order to get pointers to those classes and access to their methods. Most of the functions or methods you are supposed to call to get those pointers, in the last parameter, they ask for a "pointer to a pointer" like the one below:

HRESULT SomeClass::CreateInstance(HWND hVideo, HWND hEvent, SomeClass **ppSomeClass)


But internally, they create a "pointer to the class" (pSomeClass), they do some initialization and then they return the pointer to the caller with an asign sentence (*ppSomeClass = pSomeClass):

HRESULT SomeClass::CreateInstance(HWND hVideo, HWND hEvent, SomeClass **ppSomeClass)
{

    SomeClass *pSomeClass = new SomeClass(hVideo, hEvent);

    HRESULT hr = pSomeClass->Initialize();
    if (SUCCEEDED(hr))
    {
        *ppSomeClass = pSomeClass;
    }
    else
    {
        pSomeClass->Release();
    }
    return hr;
}


So, here comes my question:
Why to ask for a "pointer to a pointer" instead of just a "pointer" to the Class or interface in particular?

Why the above example if different than the one below (modified by me):

HRESULT SomeClass::CreateInstance(HWND hVideo, HWND hEvent, SomeClass *pSomeClass)
{
    pSomeClass = new SomeClass(hVideo, hEvent);
    HRESULT hr = pSomeClass->Initialize();
    if (SUCCEEDED(hr))
    {
        // Some code...
    }
    else
    {
        pSomeClass->Release();
    }
    return hr;
}


The above example is a SimplePlayback taken from the Microsoft site about Media Foundation Programming. I have to say that I changed the name of the class (CPlayer) for "SomeClass" and took away some distracting code.

Thanks in advance!
Lalegion.
Posted

From The COM Programmer's Cookbook, chapter COM Interfaces:
"An interface is actually a pointer to a vtable. The vtables are usually shared by multiple instances, so the methods need a different pointer to be able to find the object that the interface is attached to. This is the interface pointer, and the vtable pointer is the only thing that is accessible from it by clients of the interface".
 
Share this answer
 
The pointer variable ppSomeClass serves as a return value. Therefore, in C/C++ you have to pass it by reference. There are two ways to do this: either you pass a variable of type reference to the original type, in this case reference to pointer:
HRESULT SomeClass::CreateInstance(HWND hVideo, HWND hEvent, SomeClass *& rpSomeClass)

, or you pass a variable of type pointer to the original type, in this case pointer to pointer.
HRESULT SomeClass::CreateInstance(HWND hVideo, HWND hEvent, SomeClass ** ppSomeClass)

If you do not do that, the calling program will never see any changes to that variable as it is passed by value only.
HRESULT SomeClass::CreateInstance(HWND hVideo, HWND hEvent, SomeClass *pSomeClass) {
//...
}
void foo(HWND hVideo, HWND, hEvent) {
   SomeClass* myptr = 0;
   SomeClass::CreateInstance(hVideo, hEvent, myptr);
   if (myptr == 0)
       cout << "told you so!" << endl; // <<--- this will happen!
   else {
      // do something
   }
}


venkatmakam tried to explain that in Solution 1, so you might want to try out the code he provided.
 
Share this answer
 
I will try to give answer according to my understand about your problem.
we will go for simple program like this, which simulates your COM program.

int funPP(int **ppInt)
{
    int *x = new int;			//create a heap pointer.it will be eqaul to your function pointer.
    *ppInt = x;				// This statement effectively equal to int *pInt = new x;
    cout<<"x address : "<<x<<endl;
    return 0;
}
/*int funP(int *pInt)
{
    int *x = new int;
    pInt = x;
    cout<<"x address : "<<x<<endl;
    return 0;
}*/
int _tmain(int argc, _TCHAR* argv[])
{
    int *pInt;		//Create an initialised pointer
    //int *p1Int = new int;
    funPP(&pInt);	//pass the address.
    //funP(p1Int);
    cout <<"pInt pointing to :"<<pInt<<endl;
    //cout <<"p1Int pointing to :"<<p1Int<<endl;
	return 0;
} 

So what i want to say is <b>you are passing the address of pointer so that the pointer will get initialised
in another funtion</b>.That's it.so both x and pInt point to same location. you can try by uncommenting the lines
in above program and debug line by line so that you will know the exact problem in the second case.
 
Share this answer
 
Comments
lalegion 23-Jul-11 1:05am    
Hey!

Thank you all very much for help!

And thanks to you "venkatmakam" for that cristal clear piece of code. I did finally understand what was my mistake.
I did compile your code and I realized that when I use the "funP" function, passing my external pointer as a parameter, I'm actually setting the internal "pInt" pointer to point to whatever my external pointer happens to point, and then by doing:

pInt = x; // inside the funP function

I'm not setting my external pointer but the internal one, leaving the external "untouched".

Really interesting these little fellows "pointers" are...

Thanks again and see you around!
Lalegion.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900