What would be a set of nifty preprocessor hacks (ANSI C89/ISO C90 compatible) which enable some kind of ugly (but usable) object-orientation in C?
I am familiar with
@Adam Rosenfield has a very good explanation of how to achieve OOP with C
Besides, I would recommend you to read
1) pjsip
A very good C library for VoIP. You can learn how it achieves OOP though structs and function pointer tables
2) iOS Runtime
Learn how iOS Runtime powers Objective C. It achieves OOP through isa pointer, meta class
I think what Adam Rosenfield posted is the correct way of doing OOP in C. I'd like to add that what he shows is the implementation of the object. In other words the actual implementation would be put in the .c
file, while the interface would be put in the header .h
file. For example, using the monkey example above:
The interface would look like:
//monkey.h
struct _monkey;
typedef struct _monkey monkey;
//memory management
monkey * monkey_new();
int monkey_delete(monkey *thisobj);
//methods
void monkey_dance(monkey *thisobj);
You can see in the interface .h
file you are only defining prototypes. You can then compile the implementation part " .c
file" into a static or dynamic library. This creates encapsulation and also you can change the implementation at will. The user of your object needs to know almost nothing about the implementation of it. This also places focus on the overall design of the object.
It's my personal belief that oop is a way of conceptualizing your code structure and reusability and has really nothing to do with those other things that are added to c++ like overloading or templates. Yes those are very nice useful features but they are not representative of what object oriented programming really is.
My recommendation: keep it simple. One of the biggest issues I have is maintaining older software (sometimes over 10 years old). If the code is not simple, it can be difficult. Yes, one can write very useful OOP with polymorphism in C, but it can be difficult to read.
I prefer simple objects that encapsulate some well-defined functionality. A great example of this is GLIB2, for example a hash table:
GHastTable* my_hash = g_hash_table_new(g_str_hash, g_str_equal);
int size = g_hash_table_size(my_hash);
...
g_hash_table_remove(my_hash, some_key);
The keys are:
C Object System (COS) sounds promising (it's still in alpha version). It tries to keep minimal the available concepts for the sake of simplicity and flexibility: uniform object oriented programming including open classes, metaclasses, property metaclasses, generics, multimethods, delegation, ownership, exceptions, contracts and closures. There is a draft paper (PDF) that describes it.
Exception in C is a C89 implementation of the TRY-CATCH-FINALLY found in other OO languages. It comes with a testsuite and some examples.
Both by Laurent Deniau, which is working a lot on OOP in C.
If I were going to write OOP in C I would probably go with a pseudo-Pimpl design. Instead of passing pointers to structs, you end up passing pointers to pointers to structs. This makes the content opaque and facilitates polymorphism and inheritance.
The real problem with OOP in C is what happens when variables exit scope. There are no compiler-generated destructors and that can cause issues. Macros can possibly help, but it is always going to be ugly to look at.
Look at http://ldeniau.web.cern.ch/ldeniau/html/oopc/oopc.html. If nothing else reading through the documentation is an enlightening experience.