Skip to content

Instantly share code, notes, and snippets.

@pghalliday
Created June 16, 2012 10:00
Show Gist options
  • Save pghalliday/2940847 to your computer and use it in GitHub Desktop.
Save pghalliday/2940847 to your computer and use it in GitHub Desktop.
Object Oriented OCode Boiler Plate
#include "opentv.h"
#include "assert.h"
#include "MyClass.h"
/* This method just waits for a quit message and then exits the application */
static void Main_waitToExit(void)
{
while (TRUE)
{
o_message tMessage;
O_ui_get_event_wait(&tMessage);
if (O_msg_class(&tMessage) == MSG_CLASS_CONTROL)
{
if (O_msg_type(&tMessage) == MSG_TYPE_QUIT)
{
O_exit();
}
}
}
}
void main(void)
{
/*
record the current memory available so we
can detect memory leaks
*/
size_t uMemory = O_heap_available();
MyClass * pInstance = MyClass_create(5);
MyInterface * pInterfaceInstance = MyClass_asMyInterface(pInstance);
/* Method tests */
assert(MyClass_getMyField(pInstance) == 5);
assert(MyInterface_myMethod(pInterfaceInstance, 3) == 8);
/* Memory leak test */
MyClass_destroy(pInstance);
assert(O_heap_available() == uMemory);
/* Stick around so the VSTB does not exit and we know we ran everything */
O_debug("OOOCode: Tests passed\n");
Main_waitToExit();
}
#include "MyClass.h"
#include "opentv.h"
struct _MyClass
{
int nMyField;
};
MyClass * MyClass_create(int nMyField)
{
MyClass * pThis = O_malloc(sizeof(MyClass));
pThis->nMyField = nMyField;
return pThis;
}
void MyClass_destroy(MyClass * pThis)
{
O_free(pThis);
}
int MyClass_getMyField(MyClass * pThis)
{
return pThis->myField;
}
#ifndef MyClass_H
#define MyClass_H
typedef struct _MyClass MyClass;
extern MyClass * MyClass_create(int nMyField);
extern void MyClass_destroy(MyClass * pThis);
extern int MyClass_getMyField(MyClass * pThis);
#endif
#include "MyClass.h"
#include "opentv.h"
struct _MyClass
{
/* Need a field to store the interface instance */
MyInterface * pMyInterface;
int nMyField;
};
/*
private implementation of a MyInterface_MyMethod method - we keep
the void pointer parameter so that we don't have to cast the method
when passing it into the interface constructor. Doing so could hide nasty
type errors further down the road.
*/
static int MyClass_myMethod(void * pInstance, int nArgument)
{
/*
this #define is an optimisation that I use instead
of adding a local variable to the stack. It's pretty
optional but I worry about this sort of thing when
running code on low horsepower set top boxes
*/
#define pThis ((MyClass *) pInstance)
/* ooh, look - that's what myMethod is for ;) */
return pThis->nMyField + nArgument;
/*
let's not forget to undef pThis we may want to use
that name a lot in other methods ;)
*/
#undef pThis
}
MyClass * MyClass_create(int nMyField)
{
MyClass * pThis = O_malloc(sizeof(MyClass));
/* Construct an interface instance */
pThis->pMyInterface = MyInterface_create(pThis, MyClass_myMethod);
pThis->nMyField = nMyField;
return pThis;
}
void MyClass_destroy(MyClass * pThis)
{
/* don't forget to destroy the interface instance */
MyInterface_destroy(pThis->pMyInterface);
O_free(pThis);
}
int MyClass_getMyField(MyClass * pThis)
{
return pThis->nMyField;
}
/* Casting convention implementation */
MyInterface * MyClass_asMyInterface(MyClass * pThis)
{
return pThis->pMyInterface;
}
#ifndef MyClass_H
#define MyClass_H
/* Need to include the interface header */
#include "MyInterface.h"
typedef struct _MyClass MyClass;
extern MyClass * MyClass_create(int nMyField);
extern void MyClass_destroy(MyClass * pThis);
extern int MyClass_getMyField(MyClass * pThis);
/* New method to "cast" MyClass to MyInterface */
extern MyInterface * MyClass_asMyInterface(MyClass * pThis);
#endif
#ifndef MyInterface_H
#define MyInterface_H
#include "opentv.h"
/*
Prototype a method signature to be implemented for
this interface. Allows the compiler to spot errors
but can't get round the void pointer for the instance
*/
typedef int (* MyInterface_MyMethod)(void * pInstance, int nArgument);
/* Interface structure (vtable?) */
typedef struct
{
void * pInstance;
MyInterface_MyMethod cbMyMethod;
}
MyInterface;
/*
Interface constructor. I use static inline for all
interface methods so that they compile out much like
preprocessor stuff but also the compiler will help me
with type checking, etc
*/
static inline MyInterface * MyInterface_create(void * pInstance, MyInterface_MyMethod cbMyMethod)
{
MyInterface * pThis = O_malloc(sizeof(MyInterface));
pThis->pInstance = pInstance;
pThis->cbMyMethod = cbMyMethod;
return pThis;
}
/* Interface destructor */
static inline void MyInterface_destroy(MyInterface * pThis)
{
O_free(pThis);
}
/*
This method allows the implementation of MyInterface_MyMethod
to be called thus facilitating polymorphism which is our end goal
*/
static inline int MyInterface_myMethod(MyInterface * pThis, int nArgument)
{
return pThis->cbMyMethod(pThis->pInstance, nArgument);
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment