I'm going to take a brief break from the ContainerControl discussion to talk about an interesting hack I discovered. Don't worry, we'll get back to the ContainerControl series soon enough.
So I decided to delve a little deeper into the mysteries of COM. It always bothers me when I can do something from another language, but cannot do it in any way, shape or form from REALbasic. And our support for generic COM is almost non-existent. We've got good support for ActiveX controls (which is a form of COM), but I wanted the nity-grity generic COM support.
So the problem is this: there are certain Win32 APIs which ask for a COM object interface in order to function. So how do you implement a COM interface? Well, in C++, you'd do something like this:
class EnumerableStringList : public IEnumString
{
private:
// Our reference count, so we can be a well-behaved
// COM object.
long mRefCount;
public:
EnumerableStringList();
// Here are all the functions to support the
// IUnknown interface which every COM object needs
// to support.
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHODIMP QueryInterface( REFIID riid, void **ppvObject );
// Here are all the functions we need to support
// the IEnumString interface.
STDMETHODIMP Next( ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched );
STDMETHODIMP Skip(ULONG celt);
STDMETHODIMP Reset(void);
STDMETHODIMP Clone(IEnumString** ppenum);
};
As you can see, our class inherits from the IEnumString class (which in turn inherits from the IUnknown class), so we put in declarations for both of these interfaces so that we satisfy the interface contract. Btw, I removed the code within the methods for clarity.
The way COM works though is that the interface implementations are defined in a specific order that both the caller and the callee agree upon. So the caller tells the callee what order to call the methods in via the header file which declares the interface (such as IEnumString or IUnknown). The callee then implements the interface, and with the magic of C macros, everything is hunky dorey.
So how would this work in REALbasic?
The problem is, REALbasic isn't C or C++, so you don't have to worry about declaration vs definition, or any of that jazz. But because of it, there's no way to implement a COM interface. Or is there?
Of course there is, otherwise I wouldn't be teasing you! The magic trick is in understanding the memory layout of a COM object.
When you make a class which implements a COM interface, the memory layout will look like this:
| ClassPtr-> | vTable-> | QueryInterface |
| ... | AddRef | |
| Release | ||
| ... |
Armed with the memory layout knowledge, how do you think you'd implement a COM interface in REALbasic? Stick around for part two and see if your answer is correct.
Leave a comment