OOC is an acroynm for "Object Oriented C"
The project uses object orient design and implementations to construct a framework consisting of important data structures (some have templates :)!) that do not exist in the standard C library.
Current data structures implemented
- String
- Templated Vector
- Templated Set
- Templated Map
Sometimes, C does get a bit messy and hard to manage. The standard library can be tricky at times and there are plenty of unsafe functions that should/are deprecated. Anyone who is annoyed by the standard library or feel limited by the amount of primitive data structures in C (struct, arrays), should use this framework.
There also are Object oriented C libraries out there, but they're far too awkward to use (too C heavy-handed)
https://github.com/shichao-an/ooc
http://ooc-coding.sourceforge.net/
https://en.wikipedia.org/wiki/GObject
- Microsoft Visual Studio 2015
- Microsoft Visual Studio 2017
- gcc 4.8.4
- gcc 8.0
- clang 3.8
- clang 5.0
- clang 6.0
If clang is used, make sure -Werror is not enabled if clang >= 5.0. This will cause a c extension to fail (-Wmicrosoft-anon-struct).
The project uses cmake to generate the library and examples.
If a microsoft visual studio is used, testing will be disabled since cuint is used as the testing framework.
In top level directory of OOC
cmake -Bbuild .
There is also a Makefile in the directory as well (It does not generate a library, however)
OOC works in a similar fashion to how C++ works. Using how structs are laid out in memory, one can construct a class, a virtual function table and even runtime information for the class.
Here is an example of the vector object. It points to the vector class containing the virtual function table and other necessary information for the class. Since the vector inherits from container, which inherits from object, the vector must override the object and container methods. There is also a CompleteObjectLocator class, which contains runtime type information for casting between classes and finding out an object's type at runtime.
Each object in OOC is abstracted into its own class and implemenation details can be ignored. The same calls can be made to different objects such as String and Vector
//returns number of elements in vec
Call(Vector(int), size, vec);
//returns number of characters in str
Call(String, size, str);
The user never has to manually "grab" any data fields of an object in OOC. Therefore, all data fields are "private" and there are getter functions to grab the data.
Example with vector (stores data in contigious memory)
//get pointer to data (No need to do this)
vec->data;
//get first element of vector (more obvious that one is trying to get an int)
Call(Vector(int), get, vec, 0);
Inheritence can be done by making use of how structs are laid out in memory.
For example, the string class inherits from a container class by holding the container struct inside string struct.
typedef struct _String
{
struct Container_ container;
size_t length;
size_t capacity;
union
{
char buf[DEFAULT_STRING_LENGTH];
char* pBuf;
} data;
} *String;
Polymorphism can be done in a similar fashion to how inheritence is implemented in OOC.
For example, the string virtual function table inherits from the container virtual function table and overrides the original function in the string constructor
String Virtual Function Table
typedef struct _StringVFTable
{
struct ContainerVFTable;
void* (*set)(void* this, const char* item);
char* (*c_str)(void* this);
...
StringIterator (*end)(void* this, StringIterator iterator);
} StringVFTable;
String Constructor
void StringConstruct(void* this)
{
CHECK_NULL_NO_RET(this);
//call super class's constructor (ContainerConstruct)
ContainerConstruct(this);
//Override Object's methods
//=========================
//Set the vtable's complete object locator to complete the RTTI circle
StringvfTable.pCompleteObjectLocator = &stringCompleteObjectLocator;
//Set the equals function
StringvfTable.delete = &DeleteString;
...
//Override Container's methods
//==========================
StringvfTable.add = &StringAdd;
StringvfTable.clear = &StringClear;
...
//Initialize class member methods
//==========================
StringvfTable.set = &StringSet;
StringvfTable.c_str = &StringC_Str;
...
}
Templating
http://arnold.uthar.net/index.php?n=Work.TemplatesC
A Stackoverflow post that inspired this project
https://stackoverflow.com/questions/2181079/object-oriented-programming-in-c
A better explanation of RTTI
http://www.openrce.org/articles/full_view/23
Only one empty constructor can be made for a class
Single inheritence
Yup. I'm pretty much reinventing the wheel for implementing this framework when C++ exists. But..., sometimes one has to use C and I wanted to learn from this project. I didn't fully understand the virtual function table concept. I didn't understand how RTTI works. This project gave me insight as to how higher level languages such as java are implemented. Plus, I want to use this in my other (future) projects :).
#include "ooc.h"
int main()
{
//allocate a new string
String s1 = New(String);
//allocate a new string
String s2 = New(String);
//set s1 to "Much w0w"
Call(String, set, s1, "Much w0w");
//set s2 to " d0ge"
Call(String, set, s2, " d0ge");
//prints "Much w0w"
printf("%s\n", Call(String, c_str, s1));
//add s2 to s1
Call(String, add, s1, s2);
//prints "Much w0w d0ge"
printf("%s\n", Call(String, c_str, s1));
//manually append string literal to s1
Call(String, append, s1, " gud");
//prints "Much w0w d0ge gud"
printf("%s\n", Call(String, c_str, s1));
//free the string's resources
Delete(String, s2);
Delete(String, s1);
return 0;
}
See examples folder for more examples
Explanations of implementing object oriented in c
https://stackoverflow.com/questions/2181079/object-oriented-programming-in-c
Great Travis CI testing C example
https://github.com/softwaresaved/build_and_test_examples
RTTI
http://www.openrce.org/articles/full_view/23
https://www.blackhat.com/presentations/bh-dc-07/Sabanal_Yason/Paper/bh-dc-07-Sabanal_Yason-WP.pdf
[never done :(] Document specifications
[x] Finish string class
[x] Test string class
[x] Test on linux and create makefile
[x] Implement Dynamic cast (upcast/downcast)
[x] Explain how OOC works w/ diagrams
[x] Iterator
[x] Vector class
[x] Test Vector class
[x] Set class
[x] Map class
[ gotten better ] Provide Examples
[ sort of working(?) ] Move semantics
[ in the far future ] const Iterator
[ Kind of ugly right now ] ForEach keyword
[ really should ] Add do(){ } while(0); to macros...
[x] Change struct names beginning with underscore (nonstandard...)
[x] Consider changing microsoft version of "anonymous" structs -> requires --fms-extensions on gcc :( (Less readable and seeing what is inheritence)
[ Not sure, maybe take a look at how it's done in C++ ] Exceptions/Exception handling
[ should be simple ] Allow one to pass multiple parameters to a constructor. Add VA_ARGS to New
[x] Replace Delete(type, object) with Delete(object). Can be fixed by below
[x (OOC_V2)] Simplify library calls by templating object.h/container.h. Instead of Call(type, object, method), one can use Call(object, method) or object->Call(...)
[ Probably not ] Allow allocations on the stack and RAII like C++. Take a look at https://github.com/Snaipe/libcsptr
[ well ] C++ shared/unique_ptr
[ oof ] Default constructor / Rule of 5 / Rule of 0
[x] Easy way to initialize Object
[ oh no ] copy of vtable (upcasting...)
[ good thing? ] no multiple inheritence
Feel free to make a PR and when I have time, I'll take a look into it. :)
MIT License
Copyright (c) [2018] [Henry Zhu]
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.