Skip to content

Instantly share code, notes, and snippets.

@ddlsmurf
Last active May 22, 2021 11:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ddlsmurf/6861658 to your computer and use it in GitHub Desktop.
Save ddlsmurf/6861658 to your computer and use it in GitHub Desktop.
Example for C users of how classes and virtual lookup tables can work. Proper memory and error management left out. #tutorial #oop
basic debug on object of type 'base', data: 0xdeadbeef
basic debug on object of type 'pointer', data: 0xdeadbeef
int debug (type 'int') value: '123'
No method 'sayHi' in 'int'
string debug (type 'string') value: 'hi guys'
Howdidledidoo 'string'
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <strings.h>
struct class_instance;
typedef void (*method_pointer)(struct class_instance *self);
struct class_method {
char *name;
method_pointer function;
};
struct class_definition {
char *name;
struct class_definition *inheritedClass;
int methodCount;
struct class_method **methods;
};
struct class_instance {
struct class_definition *class;
void *instance_data;
};
struct class_definition *newClass(
char *name,
struct class_definition *inheritedClass, ...) {
va_list args;
va_list argsCopy;
va_start(args, inheritedClass);
va_copy(argsCopy, args);
int methodCount = 0;
struct class_method *dummy;
struct class_method **method;
while (dummy = va_arg(argsCopy, struct class_method *))
methodCount++;
va_end(argsCopy);
size_t size =
sizeof(struct class_definition) +
methodCount * sizeof(struct class_method *);
struct class_definition *result = malloc(size);
bzero(result, size);
result->name = name;
result->inheritedClass = inheritedClass;
result->methodCount = methodCount;
method = result->methods = (struct class_method **)(result + 1);
while (dummy = va_arg(args, struct class_method *)) {
*method = dummy;
method++;
}
va_end(args);
return result;
}
struct class_instance *newObject(struct class_definition *class, void *data) {
struct class_instance *object = malloc(sizeof(struct class_instance));
object->class = class;
object->instance_data = data;
return object;
}
method_pointer findMethod(struct class_definition *class, char *methodName) {
int i = class->methodCount;
while (i-->0) {
if (strcmp(class->methods[i]->name, methodName) == 0) {
return class->methods[i]->function;
}
}
return class->inheritedClass ? findMethod(class->inheritedClass, methodName) : 0;
}
void runMethod(struct class_instance *object, char *methodName) {
method_pointer method = findMethod(object->class, methodName);
if (method)
method(object);
else
printf("No method '%s' in '%s'\n", methodName, object->class->name);
}
void baseClassDebug(struct class_instance *self) {
printf("basic debug on object of type '%s', data: %p \n", self->class->name, self->instance_data);
}
struct class_method baseClassDebugMethod = { "debug", baseClassDebug };
void stringClassDebug(struct class_instance *self) {
printf("string debug (type '%s') value: '%s'\n", self->class->name, (char*)self->instance_data);
}
struct class_method stringClassDebugMethod = { "debug", stringClassDebug };
void stringClassSayHi(struct class_instance *self) {
printf("Howdidledidoo '%s'\n", self->class->name, (char*)self->instance_data);
}
struct class_method stringClassSayHiMethod = { "sayHi", stringClassSayHi };
void intClassDebug(struct class_instance *self) {
printf("int debug (type '%s') value: '%i'\n", self->class->name, (int)self->instance_data);
}
struct class_method intClassDebugMethod = { "debug", intClassDebug };
int main() {
/* Pseudo object code:
class base {
void *data;
void constructor(data) { this.data = data; }
void debug() { ...baseClassDebug... }
}
class pointer inherits base {
}
class string inherits base {
void debug() { ...stringClassDebug... }
void sayHi() { ...stringClassSayHiMethod... }
}
class int inherits base {
void debug() { ...intClassDebug... }
}
*/
struct class_definition *baseClass = newClass("base", 0, &baseClassDebugMethod, 0);
struct class_definition *pointerClass = newClass("pointer", baseClass, 0);
struct class_definition *stringClass = newClass("string", baseClass, &stringClassDebugMethod, &stringClassSayHiMethod, 0);
struct class_definition *intClass = newClass("int", baseClass, &intClassDebugMethod, 0);
/* objectOfBase = new base(0xdeadbeef); */
struct class_instance *objectOfBase = newObject(baseClass, (void *)0xdeadbeef);
/* objectOfBase.debug(); */
runMethod(objectOfBase, "debug");
/* objectOfPointer = new pointer(0xdeadbeef); */
struct class_instance *objectOfPointer = newObject(pointerClass, (void *)0xdeadbeef);
/* objectOfPointer.debug(); */
runMethod(objectOfPointer, "debug");
/* objectOfInt = new int(123); */
struct class_instance *objectOfInt = newObject(intClass, (void *)123);
/* objectOfInt.debug(); */
runMethod(objectOfInt, "debug");
/* objectOfInt.sayHi(); */
runMethod(objectOfInt, "sayHi");
/* objectOfString = new string("hi guys"); */
struct class_instance *objectOfString = newObject(stringClass, "hi guys");
/* objectOfString.debug(); */
runMethod(objectOfString, "debug");
/* objectOfString.sayHi(); */
runMethod(objectOfString, "sayHi");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment