Here's a pattern that pops up in C frequently that emulates OOP:
Consider a class named MyClass.
/* MyClass.h or myclass.h */
#ifndef MYCLASS_H
#define MYCLASS_H
struct myclass_s;
typedef struct myclass_s myclass_t;
myclass_t * myclass_new();
void delete_myclass(myclass_t *);
// Method int doMyStuff(int arg1,int arg2)
int myclass_doMyStuff(myclass_t *, int arg1, int arg2);
#endif //MYCLASS_H
The header file defines the type myclass_t, but hides the actual implementation myclass_s. This somewhat ackward requirement to have two names follows from C having structs in a separate namespace, while in C++ structs are in the same namespace as all other types. The code is intended to work in both C and C++. Here is the corresponding .c file:
/* MyClass.c or myclass.c */
#include "myclass.h" // Or MyClass.h
struct myclass_s {
int exampleField;
};
myclass_t * myclass_new()
{
myclass_t * o=(myclass_t*)malloc(sizeof(myclass_t));
// Initialize o here.
return o;
}
void myclass_delete(myclass_t * o)
{
// Do any cleanup needed on o here.
free(o);
}
int myclass_doMyStuff(myclass_t * o,int arg1,int arg2)
{
// ...
}
Inheritance and dynamic binding are also possible to do in C, but they are somewhat more involved. The above pattern, or any pattern that models OOP, isn't always the best way to do things in C, so try not to get hung up on the class centered way of thinking. Still, this pattern is occasionally useful. For example, libpng uses something close to this (they also do 'exceptions' using setjmp/longjmp, something which I advice against).