Pages

15 July 2011

COM (OOP) in GB32 - IUnknown (1)

In this part I'll show you the layout of a COM class as it could be implemented in GFA-BASIC 32. Note that we restrict ourselves to a minimalist COM object that supports the IUnknown interface only. We will not yet create properties and methods.
The GFA-BASIC 32 approach is loosely based on the article series COM in plain C by Jeff Glatt, specifically Part 1 and Part 2. However, in the first step we are not going to use type libraries, we are not going to store the COM object in a DLL, and we are not going to define another COM object that creates the one we define. COM is merely a binary standard; it dictates how to layout an array of function pointers and where to put the address of this array (of function pointers). It also dictates how to add reference counting. To comply to this standard a COM object must at least contain three pointers to pre-defined functions, also known as the IUnknown interface. In GFA-BASIC 32 this could look like this:

Copy it to a new GFA-BASIC 32 application and save as IUnknownBlog.g32. Try to run it; it should compile and run flawlessly. Our first minimalist COM object/class has been defined and is up and running. Of course it doesn't do anything, but the we have an object that integrates with GFA-BASIC 32 and fully complies to the COM binary standard.Assign to Object
Let us take a brief look at the code. Since this project isn't meant for the beginner, I'll walk you through it in big steps.
The Object data type holds a pointer to a piece of memory of at least 4 (lpVtbl) bytes. Mostly it contains another integer for a reference count. In GFA-BASIC 32 the Ocx variables always define their count in the second slot, we will use that as well.
To put a memory address in an Object variable we usually use Set obj2 = obj2. GFA-BASIC 32 checks for two proper COM object types at compile-time. Since we have mAlloc-ed address only this syntax wouldn't work. We must write it to Object directly. For the same reason we set the RefCount to 1 by hand.
The array of functions (VTABLE) is stored in a Type and shared with all instances of our custom COM object. Therefor a static (global) variable is used and initialized once. Each new COM object should hold the vtable-address in its lpVtbl member. _QueryInterface, _AddRef, and _Release The application COM functions _QueryInterface, _AddRef, and _Release are never called directly, but always by GFA or another COM object. They clutter up our application code and are in fact just boiler plate code. We must do something about that, for instance put them in a $Library. Also note the Naked attribute. These functions are never executed in the context of the application and need no TRACE code and Try/Catch-exception handler. They should be as naked as possible to gain the best performance.
The Trace *this commands in the code are to verify the address passed. Also note the type of the this pointer. COM passes the address of the COM object by reference and by adding the correct type into the function declaration we can access its members directly. All other parameters are simple placeholders for addresses we don't use or pass on.
In the next part we will implement an IDispatch object and try to integrate the COM code more into GFA-BASIC 32.