Object Oriented C Library - Introduction
Ah… good ol C
I have been always a big fan of C.
It’s:
- Simple - All you need to really wrap your head around are pointers and memory!
- Compact - The C standard library is tiny compared to the monster libraries that Java and C++ have.
- Powerful - C is the high-level language that is closest to assembly. One can translate C to assembly just by looking at C and have an general idea of what is happening to memory.
C has been around for ages. It hasn’t changed much, but it is still a popular language among the low-level programmers (ex. kernel dev, function/memory tools, Linus Torvald’s rants)
C the ugly side
However, there are a plethora of reasons as to why C is not an attractive modern language to work with.
- Memory management - Other languages like Java have a garbage collector, so one doesn’t have to worry about managing memory
- Suitable standard library - C standard library. There are many gotchas in the standard library. There are many deprecated functions in the standard library. There are many thread unsafe functions in the standard library. The standard library will make you sad sometimes. :(
- Getting something done - C doesn’t have vectors. C doesn’t have maps. C doesn’t really even have proper strings. C doesn’t have anything really besides pointers and memory that the programmer has to figure out how to use. This makes developing something in a timely manner incredibly frustrating and difficult.
C++ like C?
Wait. There’s still hope!
Introducing OOC! (Object oriented C library) - Github link
OOC is a library wrapper I wrote around a year ago. It is mainly influenced by C++ and has C++ like syntax.
Here is a quick example of string splitting in OOC:
An example of string splitting in C++:
As you can see, OOC’s syntax is very similar C++’s syntax, which is pretty neat since OOC is implemented in just C.
Breaking down the example
Objects in OOC are pointers since references in C do not exist. By default, everything is passed by reference (pointers, cough, cough) in OOC.
Therefore, String
type here is actually a pointer to a string struct. Vector(String)
as well is a pointer to a vector of string structs.
Every object must be allocated with the New
keyword. This is because C cannot automatically invoke the constructor when the object is declared unlike C++, which is allocated on the stack.
In addition, as I mentioned in the previous paragraph, objects in OOC are actually pointers, so they work similar to having a pointer to a class in C++.
You might have noticed that Call(...)
is used to call the appropriate function unlike:
Call
is how one calls an class’ function/method in OOC. Call
requires at least two parameters to be passed, of which the first two are the object variable
, which is str
in the example and the second is the object’s function
that we wish to call, which is find
. The rest are arguments to the function call. So, in the example above, we want str
to call find
the delimiter
at offset start_index
.
Using Call
definitely is harder to read than the C++ way, but the variable/function names are formatted in the correct order. On the technical side, the reason why Call(...)
is necessary will be discussed in a future post.
Also, NPOS
is used instead of std::string::npos
as C doesn’t have namespaces.
This is where it gets interesting. In C++11, move semantics became part of the C++ standard. To summarize, one could “move” the ownership of an object to another object or as some people describe it – “moves its guts to the new object”.
Basically, in the example above, MoveCall(directories, push_back, directory);
would transfer move directory into directories vector, thus making directory invalid to use afterwards.
Example of what I mean by invalid usage after the item has been moved:
The rest of the code should be pretty self explanatory :). Just look at the OOC and C++ example side by side.
So, how does one copy then?
To, copy, you just use Call
and not MoveCall
.
How does heck does this even work?
Magic macros.
Did you just say macros, the awful, undebuggable, copy paste preprocessor magic?
In order to implement psuedo templating and have more usable and readable API, macros are necessary.
In the next few posts, we will dive into more examples and how OOC works internally.
Extra tid bits
Current version is version 2 (OOC_V2) where the API has been simplified. If you see version 1 code (OOC_V1), the type is passed to every Call
. By default, version 2 is enabled.
Snaipe implemented smart pointers in C with gcc extensions libcsptr. This is really awesome!
Go check out his post about his project. This could be used to create a RAII-like effect with OOC.
Object Oriented C Series:
Enjoy Reading This Article?
Here are some more articles you might like to read next: