QueryInterface function of C + + COM programming (i) _c language

Source: Internet
Author: User

Objective

The component is externally disclosed is an interface; A component can implement multiple interfaces, that is, it can publish multiple interfaces, and before that, you rarely 100% to fully understand all the interfaces of a component, just as you learn to program, and you are almost impossible to become a versatile programmer. So, since we can't fully understand all the interfaces provided by a component, how can we determine in actual development whether a component provides the corresponding interface? Look at the document? Yes, it's a good idea, in the ocean of documents, find a knowledge point, it is really difficult to waste time and energy; in fact, the component itself provides an interface to its own query, asking the customer to ask the component, whether it supports an interface, and after many of these inquiries, the customer's understanding of the component will become clearer And my article and the next article is a detailed analysis and summary of this inquiry mechanism.

About IUnknown

It says that the component itself provides an interface to its own query, so what is this interface? This is the famous IUnknown interface, and the IUnknown interface is defined in the Windows SDK Unknwn.h, which is defined as follows:

Copy Code code as follows:

Interface IUnknown
{
Public
Virtual HRESULT stdmethodcalltype QueryInterface (REFIID riid, _com_outptr_ void **ppvobject) = 0;
Virtual ULONG stdmethodcalltype AddRef (void) = 0;
Virtual ULONG Stdmethodcalltype release (void) = 0;
};

The stdmethodcalltype here represents the invocation method, which is the __stdcall way of the Windows API. As you can see, a function named QueryInterface is defined in IUnknown. The customer can call QueryInterface to determine if the component supports a particular interface, and for the remaining AddRef and release two interface operations, I will summarize them in a later article.

All COM interfaces need to inherit the IUnknown interface; Therefore, if a customer has a pointer to a IUnknown interface, it does not need to know what kind of interface pointer it has, but just know that the interface can be used to query other interfaces.

Since all COM interfaces first inherit IUnknown, and based on the understanding behind the previous Article COM programming-interface, we can know that the first three functions in each interface's VTBL are Queryinterface,addref and release. This allows all COM interfaces to be treated as IUnknown interfaces. If the first three functions in the VTBL of an interface are not these three, then it will not be a COM interface. Since all interfaces are inherited from IUnknown, all interfaces support QueryInterface. Therefore, any interface of a component can be used by the customer to obtain other interfaces that it supports. Since all the interface pointers will also be IUnknown pointers, the customer does not need to maintain a single pointer to the component, and it cares only about the pointer to the interface.

Since we can only use QueryInterface to ask if the component supports an interface, but all of this is based on the IUnknown interface pointer, then how do I get a IUnknown interface pointer to the component? We can implement a CreateInstance function that creates a component and returns a IUnknown pointer, and for the customer, you can invoke CreateInstance to get IUnknown pointers instead of using the new operator. After summarizing all the basics of COM, let me say a system provides an API function to create an instance of a component.

About QueryInterface

The IUnknown contains a member function called QueryInterface that the customer can use to query whether a component supports a particular interface. If supported, QueryInterface returns a pointer to this interface, otherwise the return value will be an error code, and the customer can then query the other interfaces.

As you can see from the declaration of the QueryInterface function, QueryInterface has two parameters, the first parameter identifies the interface required by the customer, and this parameter is an interface identifier (IID) structure, in which I will summarize the knowledge of the IID. The second parameter is used to store the address of the requested interface. QueryInterface returns an HRESULT value, which is a 32-bit value with a specific structure, which I will then summarize; for the returned HRESULT value, in actual development, You need to use succeeded macros or failed macros to determine whether the HRESULT value represents success or failure.

The simple realization of QueryInterface

summed up the simple realization of the QueryInterface, plainly, is the simple factory model of the implementation; It also says that it is based on the IID interface identifier provided by the customer, and then obtains a pointer to the corresponding interface, returning a pointer to the corresponding interface; If the component supports the client-specified interface, then return the S_ OK and the corresponding pointer, if not supported, the return value should be e_nointerface and the corresponding pointer return value to NULL. The following is a simple example to illustrate the simple implementation of QueryInterface:

For example, there is a structure above; interfaces IX and iy inherit from the IUnknown interface, and the component CA implements the IX and IY interfaces, so the implementation of QueryInterface should be as follows:

Copy Code code as follows:

HRESULT __stdcall ca::queryinterface (const IID &iid, void **PPV)
{
if (iid = = IID_IUnknown)
{
*PPV = Static_cast<ix *> (this);
}
else if (iid = = Iid_ix)
{
*PPV = Static_cast<ix *> (this);
}
else if (iid = = Iid_iy)
{
*PPV = Static_cast<iy *> (this);
}
Else
{
*PPV = NULL;
return e_nointerface;
}
Static_cast<iunknown *> (*PPV)->addref ();
return S_OK;
}

Simple use of QueryInterface

When I get a IUnknown pointer, I can call the corresponding QueryInterface for query, as follows:

Copy Code code as follows:

void Fod (IUnknown *pi)
{
IX *pix = NULL;
Ask for Interface IX
HRESULT hr = Pi->queryinterface (Iid_ix, (void * *) &pix);
Check The return value
if (SUCCEEDED (HR))
{
Use the interface
Pix->fx ();
}
}

A complete example

It says so much, now provide a complete example, all the above theory of knowledge in the actual code in practice, so that you can better understand QueryInterface. (download).

Summarize

QueryInterface is simpler to understand, however, its theoretical knowledge must be mastered, theory is the basis of all, no theory as a support, any actual operation will not be so reliable and credible, so, this article summed up more than the theory. Because QueryInterface part of the content is more, the use of an article can not be summed up, so, then I will continue to summarize the second part of the QueryInterface.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.