Using interfaces in C

C is a powerful language and it’s very useful for low level system development. It’s possible to write big programs using only procedural style programming, but abstraction techniques such as object oriented programming are very useful for breaking up dependencies and keeping programs well structured. Unfortunately C does not have built in support for classes or interfaces, but it’s possible to implement at least the most basic elements using pointers and structures. The result is not very pretty, but if you are stuck in C and can’t or don’t want to use C++ then it’s for sure worth a try.

The example below shows how to create an interface “Animal” and implement it in the class “Dog”.

main.c

#include <stdio.h>
#include <stdint.h>

#include "dog.h"

int main()
{
	Animal a = dog_create();

	printf("What does the dog say? %s\n", animal_getsound(a));
	printf("The animal is %d years old\n", animal_getage(a));

	animal_destroy(a);

	return 0;
}

animal.h

#ifndef ANIMAL_H
#define ANIMAL_H

typedef struct Animal_s* Animal;

struct AnimalVtbl_s
{
	const char* (*getsound)(Animal self);
	int (*getage)(Animal self);
	void (*destroy)(Animal self);
};

struct Animal_s                                                                                                               
{                                                                                                                             
        const struct AnimalVtbl_s* vtbl;                                                                                      
        void*                      baseptr;                                                                                   
};

const char* animal_getsound(Animal self);
int animal_getage(Animal self);
void animal_destroy(Animal self);  

#endif /* ANIMAL_H */

animal.c

#include "animal.h"

const char* animal_getsound(Animal self)
{
	return self->vtbl->getsound(self);
}

int animal_getage(Animal self)                                                                                                
{                                                                                                                             
        return self->vtbl->getage(self);                                                                                      
}                                                                                                                             
    
void animal_destroy(Animal self)
{
	return self->vtbl->destroy(self);
}

dog.h

#ifndef DOG_H
#define DOG_H

#include "animal.h"

Animal dog_create();

#endif /* DOG_H */

dog.c

#include 
#include 

#include "dog.h"

typedef struct Dog_s* Dog;

struct Dog_s
{
	struct Animal_s base;
                                                                                                                         
        /* Members go here */                                                                                                 
        int age;
};

static const char* dog_getsound(Animal self)
{
	return "voff";
}

static int dog_getage(Animal super)                                                                                           
{                                                                                                                             
        Dog self = (Dog) super->baseptr;                                                                                      
                                                                                                                              
        return self->age;                                                                                                     
}      

static void dog_destroy(Animal super)
{
	Dog self = (Dog) super->baseptr;

	puts("dog_destroy");

	free(self);
}

static const struct AnimalVtbl_s table =                                                                                      
{                                                                                                                             
        .getsound = dog_getsound,                                                                                             
        .getage   = dog_getage,                                                                                               
        .destroy  = dog_destroy                                                                                               
};                                                                                                                            
                                                                                                                              
Animal dog_create(int age)                                                                                                    
{                                                                                                                             
        Dog self = calloc(sizeof(struct Dog_s), 1);                                                                           
        if (self)                                                                                                             
        {                                                                                                                     
                /* Initialize vtbl */                                                                                         
                self->base.vtbl    = &table;                                                                                  
                self->base.baseptr = self;                                                                                    
                                                                                                                              
                /* Initialize members */                                                                                      
                self->age = age;                                                                                              
        }                                                                                                                     
                                                                                                                              
        return &self->base;                                                                                                   
}

This entry was posted in Uncategorized and tagged , , , , , , , . Bookmark the permalink.

One Response to Using interfaces in C

  1. Pingback: Using multiple interfaces in C | Kristian Rumberg

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s