Click here to Skip to main content
15,897,371 members
Articles / Programming Languages / C++

COM in plain C, Part 6

Rate me:
Please Sign up or sign in to vote.
4.89/5 (32 votes)
22 Jul 2006CPOL25 min read 103.3K   2.4K   102  
How to write an ActiveX Script Host in C.
// The VTable and functions for our ISub1 sub-object (of our IMultInterface).

#include <windows.h>
#include <objbase.h>
#include <stddef.h>
#include "IMultInterface2.h"

// Here are ISub1's functions.
//
// Every COM object's interface must have the 3 functions QueryInterface(),
// AddRef(), and Release().
//
// I also chose to add an extra function to ISub1, which an app
// will call with the name ShowMessage.

// ISub1's QueryInterface()
static HRESULT STDMETHODCALLTYPE QueryInterface(ISub1 *this, REFIID vTableGuid, void **ppv)
{
	// Because ISub1 is a sub-object of one of our other COM objects (in the case, it's
	// a sub-object of our IMultInterface) then an app is allowed to call our ISub1's
	// QueryInterface to ask for a pointer not only to our ISub1 object, but also a
	// pointer to its base object, or any other sub-objects for that particular
	// IMultInterface.
	//
	// Because the base object's QueryInterface() already does all of this, the easiest
	// thing to do is somehow get a pointer to this base object, substitute it for the
	// "this" argument, and just call that base object's QueryInterface().
	//
	// Well, guess what? Because this ISub1 object is embedded right inside of its
	// IMultInterface, it's very easy to get the base object just with a little
	// pointer arithematic. Here it is:
	return(IBase_QueryInterface((IBase *)((unsigned char *)this - offsetof(IMultInterface, sub1)), vTableGuid, ppv));
}

// ISub1's AddRef()
static ULONG STDMETHODCALLTYPE AddRef(ISub1 *this)
{
	// Because ISub1 is a sub-object of our IMultInterface, then when an app
	// calls our ISub1's AddRef, we must also call its base object's AddRef to
	// increment the reference count. After all, we can't delete the base
	// object without first deleting all other sub-objects too. So to prevent
	// this from happening, we make sure that we increment the base reference
	// count every time an app AddRef()'s an ISub1.
	//
	// The easiest thing to do is somehow get a pointer to this ISub1's base
	// object, substitute it for the "this" argument, and just call that
	// base object's AddRef().
	//
	// Well, guess what? Because this ISub1 object is embedded right inside of its
	// IMultInterface, it's very easy to get the base object just with a little
	// pointer arithematic. Here it is:
	return(IBase_AddRef((IBase *)((unsigned char *)this - offsetof(IMultInterface, sub1))));
}

// ISub1's Release()
static ULONG STDMETHODCALLTYPE Release(ISub1 *this)
{
	// See AddRef() remarks above
	return(IBase_Release((IBase *)((unsigned char *)this - offsetof(IMultInterface, sub1))));
}

// ================== The following are my own extra functions added to ISub1

// ISub1's ShowMessage(). This displays the passed string in a message box
static HRESULT STDMETHODCALLTYPE ShowMessage(ISub1 *this, char *str)
{
	MessageBox(0, str, "ISub1 ShowMessage", MB_OK);
	return(NOERROR);
}

// Here is ISub1's VTable. It never changes so we can declare it
// static
static const ISub1Vtbl ISub1_Vtbl = {QueryInterface,
AddRef,
Release,
ShowMessage};

// This is just a helper function that initializes the ISub1 embedded
// inside of a IMultInterface
void initISub1(IMultInterface *myObj)
{
	// Set the VTable for the embedded ISub1
	myObj->sub1.lpVtbl = (ISub1Vtbl *)&ISub1_Vtbl;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions