Implementing a PODS interface in C

Now that you know how an interface is defined in C, let us see how to implement a hypothetical PODSCounter object: a PODS object that implements the PODSCounter interface. One possible implementation would be:

typedef struct MyPODSCounter {
  PODSCounter base;
  PODSInt32 count;
} MyPODSCounter;

static void MySetCount(PODSCounter* c, PODSInt32 newCount)
{
  MyPODSCounter* m = (MyPODSCounter* ) c;
  m->count = newCount;
}

static PODSInt32 MyGetCount(PODSCounter* c)
{
  MyPODSCounter* m = (MyPODSCounter* ) c;
  return m->count;
}

static void MyIncrement(PODSCounter* c)
{
  MyPODSCounter* m = (MyPODSCounter* ) c;
  ++m->count;
}

PODSCounter* MyCounterNew()
{
  static PODSCounterVTable* vtable;
  MyPODSCounter* m;

  if (!vtable) {
    vtable = (PODSCounterVTable* ) malloc(sizeof(PODSCounterVTable));
    vtable->m_setCount = &MySetCount;
    vtable->m_getCount = &MyGetCount;
    vtable->m_increment = &MyIncrement;
  }

  m = (MyPODSCounter* ) malloc(sizeof(MyPODSCounter));
  m->base.vtable = vtable;
  m->count = 0;
  return &m->base;
}

In this example, the MyPODSCounter structure is used to store objects that implement the PODSCounter interface. The MyPODSCounter structure extends the PODSCounter structure by including a PODSCounter as its first element.

MyPODSCounter adds a field I to hold the actual count in this particular PODSCounter implementation. The field I is private to the MyPODSCounter implementation: it is not visible to code that uses the PODSCounter structure.

The above methods MySetCount, MyGetCount, and MyIncrement implement each of the methods defined by the PODSCounter interface. Each of these methods takes a PODSCounter, not a MyPODSCounter, as its first argument, so that each method's definition matches its method definition in the PODSCounterVTable structure. Each of these methods can only be called with a MyPODSCounter object, so each method uses a typecast to convert the method's first argument to a MyPODSCounter. This is a common design pattern in code used to implement a PODS interface.

The method MyCounterNew is used to create a new MyPODSCounter object that implements the PODSCounter interface. The MyCounterNew method returns a PODSCounter, not a MyPODSCounter. The structure MyPODSCounter is private to the implementation and callers would use a MyPODSCounter object only by accessing its methods through the PODSCounter interface. The static variable vtable holds a vtable that is shared by all MyPODSCounter objects. Vtables should be shared among objects of the same class.

In this example, you could create a new vtable for each MyPODSCounter object, but that would only waste space, because all MyPODSCounter vtables would contain the same data and never would change.

Note

You cannot use a static variable in a POD on devices running Palm OS, where PODS cannot have any global or static data. For more information, see Coding without globals on Palm OS.

The last line of the method newMyCounter() converts a MyPODSCounter* into a PODSCounter* by taking the address of the PODSCounter structure, which is the first element of MyPODSCounter. Alternatively, you could write:

return (PODSCounter* ) m;