Object
Oriented Programming
in C
|
Laurent
Deniau
November 2006
Revised August 2007
Over the past years (2000-2008), I have developed some
frameworks to explore various object models and simplify object
oriented programming in C. This page
contains some comments and links on these tentatives. All these
frameworks try
to achieve some general principles about programming which I consider
of
importance in the following order:
- Simplicity
- Flexibility
- Extensibility
- Efficiency
- Portability
|
The motivation to develop such frameworks on top of the C language may
not be obvious. While many new languages appear each year with new
syntax and little new concepts, I prefer to try to lift C up to the
level of other high level
languages. C is portable, efficient, widely available and
standardized. This is probably why it is also the reference for other
languages when memory and speed efficiency matter and why
most
languages have a Foreign Function Interface to C. Still, many virtual
machines, interpreters, compilers or operating systems are written in
C. If one often
blame C to be a low level language similar to a super assembler, it
should be worthwhile to raise C to the level of the other high level OO
languages (and
beyond?).
This is the aim of the following frameworks entirely written in ISO C.
- C Object System
(COS) is the most recent framework with about 7,000 sloc and certainly
the one which fulfills
the best the five principles. It is now accessible on GitHub and described in these draft papers
DLS'09 [size=420kB] and
OOPSLA'09 [size=992kB].
It is strongly inspired from CLOS
and Objective-C and to a
lesser extend
by Cecil, Dylan, Haskell, Python, Slate and SmallTalk. 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, properties, exceptions, contracts and closures.
COS design is tuned to provide
efficient
portable implementation of these
concepts, specially dynamic message
dispatch
(x1.7-x2.3 slower than an indirect function call and about
x1.2-x1.5 faster than Objective-C) as well as generic message forwarding
(as
fast as message dispatch and about x40-x80 faster than Objective-C). On
top of
these
concepts, it is easy to implement high order messages,
class-predicate dispatch, multiple inheritance, dynamic inheritance,
dynamic classes, adaptive
object model, reflection and advanced memory
management. It also simplifies the programming of multi-agent
systems, distributed
systems or adaptive systems.
COS seems to
achieve the principles 1-2-3
as well as existing mainstream scripting
languages
(e.g. PHP, Python, Ruby, SmallTalk) while keeping principles 4-5 in
the range of
C. Nevertheless, COS is compliant with POSIX threads and requires a
(moderately compliant) C99 compiler.
- Object
Oriented C release
2 (OOC-2.0) is the most complete framework for the moment with about
25,000 sloc, but it
should be supplanted soon by its successor (COS). Unfortunately, it
achieves the principles 1-2-3 only partially. Mainly because it was
strongly inspired from Java
with both speed and space efficiency in mind. It supports static typing
while minimizing arbitrary cast and like most OO languages, it requires
some coding convention
for
class interface and implementation. This is the price to pay for
compile time checks. It provides the fundamental concepts
available in Java plus explicit
metaclasses
which allow to build some bidimensional class relationship (derives-from and is-a) used in dynamic object
models. As in Java (and unlike C++),
all classes are objects, all objects are polymorphic and all member
functions are
virtual. These similarities allowed to port the JUnit framework in a
week and part of JDBC in 6 weeks using OOC support for class and method
reflection as well as dynamic class creation at runtime. OOC supports
POSIX
threads and requires a C89
compiler, but the availability of a C99
compiler provides better syntactic sugar (i.e. variadic macros).
For the moment, you can
download [size=506kB]
the
tarball
as-is.
This code is NOT for software
distribution and comes without any guarantee of any sort. I plan to use
the GPL license for the first public release. The
development was stopped during the phase of code cleaning and some
work remains to make it clean and usable for large project. Part of the
code do not compile (i.e. ooc-db module which was written on
top of an old version of OOC-2.0) and the manual is obsolete but
looking at the code of some classes should be enough to be able to use
it. For the moment, this code is
only provided for curiosity
purpose, but if enough people are interested by this framework, I will
update the manual and continue to develop and maintain the core part
(i.e. ooc-core) which is the only usable and required part for serious
OOPC. The compagnion library (i.e. ooc-std) is incomplete and untested,
but it could be used as a start to develop a useful library on top of
OOC-2.0.
Acknowledgment: I
would like to thanks
Ovidiu Achim who
wrote the objects fast allocator, the testsuite of ooc-core, most
of the code you may find in the ooc-std library and did the port of
JUnit. And
Florent Georges who did a
partial port of JDBC (code in
ooc-db).
- Object
Oriented C release 1 (OOC-1.0) is the predecessor of OOC-2.0 but
it is completely different with about 20,000 sloc. It was strongly
inspired by C++ and fully
oriented toward
efficiency with a lot of inlining. It supports only single inheritance
and (unlike OOC-2.0)
does not provide protocols (Java-like interfaces), a combination which
does not offer enough flexibility for serious programming. It has a lot
of
template code (using complex macros construction)
making its use somehow difficult and partially unsafe due to the abuse
of cast
and inlining. It will probably never be publicly available even if some
people got private copies for curiosity purpose.
- Object
Oriented Programming in C (OOPC) was my first try with about
1,250 sloc (light!). It is
inspired from the C++ object
model but as for OOC-1.0, it requires some odd coding and
static cast. This is typically what you may find in the litterature (or
on the web) when looking for OOPC
techniques.
You can take a look here for
more information.
- Object
Oriented C - Simplified release is an oversimplified version of OOC-2.0
with about 300 sloc (ultra light!), which provides some very simple
coding guidelines
and programming
techniques to allow C programmers to write object oriented program
nearly as in Java. OOC-S provides some object oriented features like class (i.e. TYPE and INTERFACE), single inheritance of class, attribute access control, java-like
interface, interface default method implementation, multiple
inheritance of interfaces and ownership management
(including autorelease). OOC-S is not a framework and minimizes the use
of macros (one per class) and typedefs (none) and therefore requires
some manual coding (class initialization) and some care from the
programmer. Following OOC-S templates or examples with all compiler
warning options enabled should avoid most common mistakes and
forgetting. One can still build some macros on top of OOC-S to
automatize some part of the coding. OOC-S requires a C89
compiler. download
[size=18kB].
- Exception
in C is a C89 implementation of the TRY-CATCH-FINALLY
found in other OO languages, with the PRT-UNPRT
ressource protection mechanism and the signal-to-exception conversion.
It comes with a testsuite and some
examples. download
[size=5kB, SLOC=319].
- C++
Object Model is a long paper (see object_model.html)
started years ago which I unfortunately never finished
(about 25% achieved), but is enough to understand the overall. It comes
with a
complete example in C (see cmd_c.sh) and C++ (see cmd_cpp.sh) which
describes one way to implement the C++ object model (i.e. the g++'s
object
model). It is addressed to advanced (and motivated ;-) C
and C++ programmers who have some interest in the C++ object model, so
I
put it here
for curiosity. It may
give you
some hints about the implementation complexity corresponding to the
management of dynamic types within
constructors and destructors (i.e. intermediate
vtbl) and
covariant and contravariant types in the presence of multiple and
virtual inheritance
(i.e. thunks). I found
interesting that my naive implementation of dynamic_cast is about x3
faster than the dynamic_cast provided by g++ ;-)
Laurent Deniau, last
change 2007-03-26