Skip to content

Instantly share code, notes, and snippets.

@monocasa
Created January 22, 2015 17:52
Show Gist options
  • Save monocasa/b755ee3715697ec0f850 to your computer and use it in GitHub Desktop.
Save monocasa/b755ee3715697ec0f850 to your computer and use it in GitHub Desktop.
C Dynamic Dispatch
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
struct Petable
{
void (*pet)(struct Petable *this);
};
struct Cat
{
struct Petable petable;
const char *name;
};
static void _cat_pet(struct Petable *petable_this)
{
struct Cat *this = container_of(petable_this, struct Cat, petable);
printf("%s the cat was pet. Meow!\n", this->name);
}
struct Cat* cat_init(const char *name)
{
struct Cat *cat = malloc(sizeof(struct Cat));
if( cat ) {
cat->petable.pet = _cat_pet;
cat->name = name;
return cat;
}
else {
return NULL;
}
}
void cat_destroy(struct Cat *cat)
{
if( cat ) {
free(cat);
}
}
struct Dog
{
const char *masters_name;
struct Petable petable;
};
static void _dog_pet(struct Petable *petable_this)
{
struct Dog *this = container_of(petable_this, struct Dog, petable);
printf("%s's dog was pet. Woof!\n", this->masters_name);
}
struct Dog* dog_init(const char *masters_name)
{
struct Dog *dog = malloc(sizeof(struct Dog));
if( dog ) {
dog->masters_name = masters_name;
dog->petable.pet = _dog_pet;
return dog;
}
else {
return NULL;
}
}
void dog_destroy(struct Dog *dog)
{
if( dog ) {
free( dog );
}
}
void love_on_petable_animal(struct Petable *petable)
{
petable->pet(petable);
}
int main()
{
struct Cat *cat = cat_init("Sparkles");
struct Dog *dog = dog_init("moncasa");
if( !cat || !dog ) {
goto error_cleaup;
}
love_on_petable_animal(&cat->petable);
love_on_petable_animal(&dog->petable);
error_cleaup:
cat_destroy(cat);
dog_destroy(dog);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment