I also have an example of basic class emulation in C [the OP specified for a specific application, although, this answer is to the general question]:
A header file called "c_class.h"
#ifndef CLASS_HEADER_H
#define CLASS_HEADER_H
// Function pointer prototypes used by these classes
typedef int sub_func_t (int);
typedef float sub_funcf_t (int,int);
/* class type definition
(emulated class type definition; C doesn't really have class types) */
typedef struct {
//Data Variables
int a;
/*Function (also known as Method) pointers
(note that different functions have the same function pointer prototype)*/
sub_func_t* add;
sub_func_t* subt;
sub_func_t* mult;
sub_funcf_t* div;
} class_name;
// class init prototypes
// These inits connect the function pointers to specific functions
// and initialize the variables.
class_name* class_init_ptr (int, sub_func_t*, sub_func_t*, sub_func_t*, sub_funcf_t*);
class_name class_init (int, sub_func_t*, sub_func_t*, sub_func_t*, sub_funcf_t*);
#endif
A source code file called "c_class.c"
//gcc -o c_class c_class.c
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"c_class.h"
// The class function definitions.
/*
If we make these member functions static then they are only
accessible via code from this file.
However, we can still pass the class-like objects around a
larger program and access their member functions,
just like in any OO language.
It is possible to emulate inheritance by declaring a class object
from the class type definition (I don't touch on these more
abstract subjects though, this is only a basic class emulation).
*/
static int AddFunc(int num){
num++;
return num;
}
static int SubtFunc(int num){
num--;
return num;
}
static int MultFunc(int num){
num *= num;
return num;
}
static float DivFunc(int num, int denom){
float fnum = (float)num / (float)denom;
return fnum;
}
// The class init function definitions.
class_name* class_init_ptr (int num, sub_func_t* addition, sub_func_t* subtraction, sub_func_t* multiplication, sub_funcf_t* division)
{
class_name* new_class = malloc(sizeof(*new_class));
assert(new_class != NULL);
*new_class = (class_name){num, addition, subtraction, multiplication, division};
/*We could also just type:
new_class->a = num;
new_class->add = addition;
new_class->subt = subtraction;
new_class->mult = multiplication;
new_class->div = division;
*/
return new_class;
}
class_name class_init(int num, sub_func_t* addition, sub_func_t* subtraction, sub_func_t* multiplication, sub_funcf_t* division)
{
class_name new_class;
new_class = (class_name){num, addition, subtraction, multiplication, division};
/* We could also just type:
new_class.a = num;
new_class.add = addition;
new_class.subt = subtraction;
new_class.mult = multiplication;
new_class.div = division;
*/
return new_class;
}
//Working Function Prototypes
class_name* Working_Function(class_name*);
class_name Working_Function_Two(class_name);
int main(){
/* It's possible to connect the functions within the init also,
w/o sending them. */
class_name *MyClass = class_init_ptr(5, AddFunc, SubtFunc, MultFunc, DivFunc);
class_name MyOtherClass = class_init(0, AddFunc, SubtFunc, MultFunc, DivFunc);
printf("%i\n",MyClass->add(100));// 101
printf("%i\n",MyClass->subt(100));// 99
printf("%i\n",MyClass->mult(100));// 10000
printf("%f\n",MyClass->div(MyClass->a,2)); // 2.5
printf("%i\n",MyClass->mult(MyClass->mult(100))); //100000000
MyClass = Working_Function(MyClass);
//This would work also (because we're passing a pointer):
//Working_Function(MyClass);
printf("%i\n",MyClass->a); //a = 5000
MyOtherClass = Working_Function_Two(MyOtherClass);
printf("%i\n",MyOtherClass.a); //a = 9999
MyOtherClass.a = 25;
Working_Function_Two(MyOtherClass); //pass by value
printf("%i\n",MyOtherClass.a); //a = 25 (no value change)
Working_Function(&MyOtherClass); //pass by reference
printf("%i\n",MyOtherClass.a); //a = 5000 (value changed)
return 0;
}
//Working Functions
class_name* Working_Function(class_name* PassedClass){
printf("%i\n",PassedClass->a);// 5, then 25
printf("%i\n",PassedClass->add(PassedClass->a));// 6, then 26
PassedClass->a = 5000;
return PassedClass;
}
class_name Working_Function_Two(class_name PassedClass){
printf("%i\n",PassedClass.a);// 0, then 25
printf("%i\n",PassedClass.add(PassedClass.a));// 1, then 26
PassedClass.a = 9999;
return PassedClass;
}
/* We're passing emulated class objects and emulated class pointers
by reference and value, if everything works it should print this:
101
99
10000
2.500000
100000000
5
6
5000
0
1
9999
25
26
25
25
26
5000
*/