Feeling OOP in C

C language is old(since 1972 to be precise) but still kicks ass. Some folks consider C too low level. IMHO is not that low level, actually, there are some abstractions and syntactical sugars I miss in C but IMHO is something you can leave without since you are befiniting from better performance.

Many developers care too much about syntax today and not many care about performance. It really depends on what you are doing and what kind of company you are. There are languages that are more productive than C for sure, however, once you get how to do things properly is not bad at all actually is quite good.  Most of the big languages like Java, C#, python, ruby are actually based on C.

C often is a language the most of people fear it. Maybe because we got used to much with languages that do a lot of things for us. IMHO is not that hard, it's just a matter of taste, after some time I learn to enjoy working with C professionally and today I like it a lot. But this really depends on your experiences and what you really need to do - I would not build and web app in C :-)

OOP in C

C is not an Object Oriented language, C is an imperative and procedural language. However, when you stop to think about Object Orientation you might realize a could of things:
  1. You don't need it all the times - Functional Programming is a good example of it.
  2. OOP is 2 things like most of the things: (A) Ideas and (B) Syntactical sugar.

In regards to Syntactical Sugar C won't help you much. But on (A) ideas we can we apply OOP ideas is C pretty easily. There language constructs in C such as struct, typedef and function pointers that can help us to emulate OOP ideas in C.  So for this blog post, I will show how to do a very simple OOP emulation in C using this resources(struct, typedef and function pointers) we will use header files in combination with standard source files.

I use Gnome Ubuntu(so I will be using GCC) however we are talking about ideas and concepts you should be able to apply some ideas to other C compilers since we also are talking about standard C or also know as C ANSI.

Basic Structure a.k.a Fields

Here we are the basic structure. We are adding a header file. So you can think of a header file as your contract, so this is pretty much generic, you can also think of the header file as your interface. Where you will define the methods/functions your object will have. Our Object will be the typedef/struct defined there called: Coordinate. Imagine you are building a Geo-Location based solution and you need to deal with points. So this would be a good abstraction.

Our Coordinate Object has 2 properties or fields called x and y which represent our coordinates. The fields x and y are integers so we have  4 bytes for each number. After this 2 fields, we have the contractor methods our concrete class will need to imṕlement.

There are no interfaces in C however with header files and structs we can emulate implementation of this functions also called methods on OOP. So the trick here is that we define function pointers and we have specific names attached to this function pointer like setx, sety and print. If you came from java you might say that this syntax is wrong and we suppose to be using camel case convention and be something like setX and setY but since we are in C and this is just a feeling on OOP we are fine :D

Function pointers, in this case, are function pointer to void so this means if there is any value we need to pass back to the caller it needs to be via reference. Since we are setting values and printing on the console we are fine so we don't need pass values via reference - passing values to the function via value is fine.

There are also 2 functions outside of the struct/typedef Coordinate which is newCoordinate which is our OOP Constructor, so we will use this function to alocate struct in the memory in OOP words to instantiate our "Object" and the second function is called destroyCoordinate to be our destructor since C does not have garbage collector is important to us to deallocate memory when we don't need it anymore so we don't create memory leaks. So this is why we need a destructor. You don't need that in Java because Java has a garbage collector and the JVM does that for you(which a small price - not so small in big applications :-) ).

Concrete Implementation

Now let's goto our concrete implementation. Like in OOP when you have a class that implements an interface it's what we are doing it here. So in order to do it so we need to include the header file so we need to include the previous file called coordinates.h and then we can start providing functions.

Let's take a look at the code.

So if you know Python this code might look familiar to you :-) So here we have implementations of the functions: setx, sety, print, constructor, and destructor. There is one particular thing that is important we are always receiving a pointer to our struct Coordinate called *this.

Going back to the constructor we see the newCoordinate function which receives void and returns a pointer to Coordinate typedef/struct which is our "Object". Here we are doing 3 important things. First of all, we are allocating the object in the memory using malloc and then we are setting the default values of the object which for fields x and y are ZERO. Most importantly we are binding function pointer to a method so here, for instance, you can see things like c->setx = &coordinate_setx; This is how we tell our struct to use a specific method. This is OOP would be similar to make an interface to implement a method.  Finally, we have the destructor which is calling the free function to remove the object from memory.

Calling the Code 

Right now is the final part. We need call our "Object".  We need to include our coordinates.c source file and also create a main method in other to run the application. I will also use GCC in order to complete the code and generate the binary executable program.

Let's take a look at the code first:

As you can see we are calling the constructor to create 2 "objects" coordinates and them we are setting values for x and y and printing on the console the coordinates. Finally, are destroying the objects with our constructor and avoiding memory leaks.

Now we need to compile the code with GCC and run the program. Let's go to terminal and do it:
$ gcc -o main coordinates_main.c
$  ./main

You should see an output like this:

Coordinate[x: 1, y: 2]
Coordinate[x: 3, y: 4]

So that's it, folks. I hope you could grasp how we can emulate OOP ideas in C and have the code in a way that's easier to understand and more natural for us that came from high-level languages like Java and Scala(In my case). If you want the complete code you can check it out on my GitHub here: https://github.com/diegopacheco/c-playground/tree/master/oop .

Diego Pacheco

Popular posts from this blog

Podman in Linux

Java Agents

Manage Work not People