Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Object-oriented programming in standard ANSI C

79 views
Skip to first unread message

Thierry Chappuis

unread,
Nov 15, 2006, 5:28:02 AM11/15/06
to
Hi,

I'm interested in techniques used to program in an object-oriented way
using the C ANSI language. I'm studying the GObject library and Laurent
Deniau's OOPC framework published on his web site at
http://ldeniau.web.cern.ch/ldeniau/html/oopc/oopc.html. The approach is
very instructive. I know that I could do much of this stuff with e.g.
C++, but the intellectual challenge of implementing these concepts with
pure ANSI C is relevant to me.

Are you aware of another approaches? Any experience in using such
techniques in production code? The use of GObject seems to be well
implemented in the GNOME world, but I didn't find much about Laurent
Deniau's OOPC. Have you some comments about the strengths and drawbacks
of such techniques?

Many thanks for your valuable help and comments

Best regards

Thierry

Cong Wang

unread,
Nov 15, 2006, 10:15:11 AM11/15/06
to

On Nov 15, 6:28 pm, "Thierry Chappuis" <thie...@mujigka.ch> wrote:
> Hi,
>
> I'm interested in techniques used to program in an object-oriented way
> using the C ANSI language. I'm studying the GObject library and Laurent

> Deniau's OOPC framework published on his web site athttp://ldeniau.web.cern.ch/ldeniau/html/oopc/oopc.html. The approach is


> very instructive. I know that I could do much of this stuff with e.g.
> C++, but the intellectual challenge of implementing these concepts with
> pure ANSI C is relevant to me.
>
> Are you aware of another approaches? Any experience in using such
> techniques in production code? The use of GObject seems to be well
> implemented in the GNOME world, but I didn't find much about Laurent
> Deniau's OOPC. Have you some comments about the strengths and drawbacks
> of such techniques?
>
> Many thanks for your valuable help and comments
>
> Best regards
>
> Thierry

Yeah. This is an interesting topic. In fact, C can NOT fully support
OOP like C++, but we can use some tricks to make it *like* an
object-oriented programming language. For example, we can use
structures to replace classes, use function pointer as a member of a
structure like a method of a class. And in fact, in Linux kernel source
code, there are really such OO ideas applied.

raz...@gmail.com

unread,
Nov 15, 2006, 10:51:59 AM11/15/06
to
On Nov 15, 10:15 am, "Cong Wang" <xiyou.wangc...@gmail.com> wrote:
> > ThierryYeah. This is an interesting topic. In fact, C can NOT fully support

> OOP like C++, but we can use some tricks to make it *like* an
> object-oriented programming language. For example, we can use
> structures to replace classes, use function pointer as a member of a
> structure like a method of a class. And in fact, in Linux kernel source
> code, there are really such OO ideas applied.

That's just one of the three requirements for an OO programming
language, encapsulation. The other two are inheritance and
polymorphism, and those are much more difficult to emulate in C. I've
seen inheritance attempted by exploiting the fact that C will let you
cast any type to any other type without complaining. So basically:

struct Parent
{
int a,b;
};

struct Child
{
int a,b;
more variables
};

struct Child2
{
int a,b;
more variables
}

If you want to pass a Child or a Child2 to a function, instead of
making two version of the function (which need different names because
there is no overloading in C), you can make the function take a Parent,
and then pass a Child or a Child2 'c' by saying (Parent)c. I'm not
sure if this just happens to work, or if it is actually defined in the
C standard that the variables of a structure appear in memory in the
order that they are specified in the declaration.

I haven't seen any way to do polymorphism. I guess that's kind of like
templates in C++, although templates are technically not polymorphism,
they are a hack to acheive the effect of polymorphism. This is because
the templates are handled at compile time, and true OO polymorphism is
runtime polymorphism.

Colin K.

santosh

unread,
Nov 15, 2006, 11:01:16 AM11/15/06
to
raza...@gmail.com wrote:
> On Nov 15, 10:15 am, "Cong Wang" <xiyou.wangc...@gmail.com> wrote:
> > > ThierryYeah. This is an interesting topic. In fact, C can NOT fully support
> > OOP like C++, but we can use some tricks to make it *like* an
> > object-oriented programming language. For example, we can use
> > structures to replace classes, use function pointer as a member of a
> > structure like a method of a class. And in fact, in Linux kernel source
> > code, there are really such OO ideas applied.
>
> That's just one of the three requirements for an OO programming
> language, encapsulation. The other two are inheritance and
> polymorphism, and those are much more difficult to emulate in C. I've
> seen inheritance attempted by exploiting the fact that C will let you
> cast any type to any other type without complaining.
<snip>
> I haven't seen any way to do polymorphism...
<snip>

But the biggest gain of all in using a true OO enabled language like
C++ is the compiler support for OO constructs. C wasn't designed for
OOP and with increasing availability of C++ compilers for most
non-embedded platforms, it would be wiser to use the latter, (or
another OO language), unless there're strong reasons to favour C, (like
writing low-level system code, or desiring maximum portability etc).

Chris Dollin

unread,
Nov 15, 2006, 11:16:49 AM11/15/06
to
Cong Wang wrote:

> Yeah. This is an interesting topic. In fact, C can NOT fully support
> OOP like C++,

It doesn't have syntactic support -- and that makes writing OO
code a real bigger -- but you can do polymorphism/inheritance
if you must; I think there's just enough room in the Standard
to make the required machinery legal.

Painful, but possible.

Who knows. Maybe someone could write a translator from an OO
language like C++ into pure C! Do you think that's possible?

--
Chris "Cleft? Cright? Cback? Cside? I do like to be ..." Dollin
Nit-picking is best done among friends.

Fred Kleinschmidt

unread,
Nov 15, 2006, 11:04:09 AM11/15/06
to

"Thierry Chappuis" <thi...@mujigka.ch> wrote in message
news:1163586482....@i42g2000cwa.googlegroups.com...

Look at the way a Widget is defined in the Unix Xt or Motif libraries.
--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Software Reuse Project


santosh

unread,
Nov 15, 2006, 11:21:44 AM11/15/06
to
Chris Dollin wrote:
> Cong Wang wrote:
>
> > Yeah. This is an interesting topic. In fact, C can NOT fully support
> > OOP like C++,
<snip>

> Who knows. Maybe someone could write a translator from an OO
> language like C++ into pure C! Do you think that's possible?

Didn't very early versions of g++ do that?

Richard Tobin

unread,
Nov 15, 2006, 11:31:53 AM11/15/06
to
In article <1163605918....@i42g2000cwa.googlegroups.com>,
<raz...@gmail.com> wrote:

>That's just one of the three requirements for an OO programming
>language, encapsulation. The other two are inheritance and
>polymorphism

Requirements? Common characteristics perhaps.

>struct Parent
>{
> int a,b;
>};
>
>struct Child
>{
> int a,b;
> more variables
>};

>
>struct Child2
>{
> int a,b;
> more variables
>}
>
>If you want to pass a Child or a Child2 to a function, instead of
>making two version of the function (which need different names because
>there is no overloading in C), you can make the function take a Parent,
>and then pass a Child or a Child2 'c' by saying (Parent)c. I'm not
>sure if this just happens to work, or if it is actually defined in the
>C standard that the variables of a structure appear in memory in the
>order that they are specified in the declaration.

The structure specifies that given a union of two struct types with
common initial sequences, you can access that common part through
either of the union members. Since given independent compilation it
is often impossible to be certain whether a structure is in a union
with another suitable type, in practice this is guaranteed to work.

>I haven't seen any way to do polymorphism.

Structures containing pointers to functions. For example, give every
type that can draw itself a member void (*draw)(Type obj, Screen screen),
and call obj->draw(obj, screen). Not very elegant, but you can define
a wrapper.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.

Richard Tobin

unread,
Nov 15, 2006, 11:33:12 AM11/15/06
to
In article <ejffdp$g3n$1...@pc-news.cogsci.ed.ac.uk>, I wrote:

>The structure specifies that given a union of two struct types with

^^^^^^^^^

This should have read "standard" of course.

Jean-Marc Bourguet

unread,
Nov 15, 2006, 11:52:46 AM11/15/06
to
"santosh" <santo...@gmail.com> writes:

> Chris Dollin wrote:
> > Cong Wang wrote:
> >
> > > Yeah. This is an interesting topic. In fact, C can NOT fully support
> > > OOP like C++,
> <snip>
>
> > Who knows. Maybe someone could write a translator from an OO
> > language like C++ into pure C! Do you think that's possible?

At the very worse, one would code in C an emulator for a x86 and then run
the emulator on the generated X86 code which would be a very large constant
for the program. Obviously C can be coded at such a low level than there
are better approaches.

BTW, C code is quite common as a target langage for early compilers of new
langages.



> Didn't very early versions of g++ do that?

Not that I know of. CFront did that. Comeau still do it. I think EDG
provides an example back end for its front end which does it.

That's not very different that doing a compiler. What would be more
problematic is doing such a compiler which produce mainable C code.

Yours,

--
Jean-Marc

Thierry Chappuis

unread,
Nov 15, 2006, 12:07:12 PM11/15/06
to

> I haven't seen any way to do polymorphism. I guess that's kind of like
> templates in C++, although templates are technically not polymorphism,
> they are a hack to acheive the effect of polymorphism. This is because
> the templates are handled at compile time, and true OO polymorphism is
> runtime polymorphism.
>

It is quite easy to implement something like polymorphism using
function pointers (very simplified):

struct Parent {
int data;
void (*print)(void);
};

struct Child {
int data;
void(*print)(void);
int data2;
int (*getData2)(void);
};

In the code above, function pointers can be mapped to specialized
fonctions at object creation time. However, data alignment is matter of
concern, especially when complicated inheritance shemes or multiple
inheritance are involved. It seems to be more common practice to group
all function pointers in a separate structure called virtual table
(from C++ terminology):

struct Parent {
struct Parent_virtual_table *_vptr; /* pointer to a structure
containing function pointers*/
int data_parent;
}

The above-mentioned Laurent Deniau's web site present a quite usable
object model that implements both simple and multiple inheritance, and
virtual (object functions) and non-virtual functions (class functions),
based on the C++ object model. I'm still studying the limits of the
model proposed and I'm interested in all suggestions and experiences in
this field.

I'm interested in earing from the experience of some of use about the
use of some OO-like constructs in moderately large C ANSI projects. It
sees not too complicated to design basic OO stuffs usable for
small/medium-size projects.

Moreover, coming from the linux world, I'm still looking inside the
gobject model and try to gain some experience with it. Your comments
are wellcome!

I know that I can do OOP much more easily using C++, but implementing
its concepts in pure ANSI C makes me more aware of the underlying
mechanisms, and helps me to organsize my C code in more modular way.

Thierry

William Hughes

unread,
Nov 15, 2006, 12:28:44 PM11/15/06
to

Chris Dollin wrote:
> Cong Wang wrote:
>
> > Yeah. This is an interesting topic. In fact, C can NOT fully support
> > OOP like C++,
>
> It doesn't have syntactic support -- and that makes writing OO
> code a real bigger -- but you can do polymorphism/inheritance
> if you must; I think there's just enough room in the Standard
> to make the required machinery legal.
>
> Painful, but possible.
>
> Who knows. Maybe someone could write a translator from an OO
> language like C++ into pure C! Do you think that's possible?
>

I think you would call it a compiler. You might even call
it

raz...@gmail.com

unread,
Nov 15, 2006, 1:14:54 PM11/15/06
to
On Nov 15, 11:31 am, rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
> In article <1163605918.137964.21...@i42g2000cwa.googlegroups.com>,

>
> <raza...@gmail.com> wrote:
> >That's just one of the three requirements for an OO programming
> >language, encapsulation. The other two are inheritance and
> >polymorphismRequirements? Common characteristics perhaps.
>
>

I guess 'requirements' was a strong word. The programming language
textbooks I've seen all list those three as necessary for OO languages.
The line between OO and iterative languages is much fuzzier than
between (I don't remember the exact terms) iterative, functional (e.g.
Lisp) and logical (e.g. Prolog).

Colin K.

Malcolm

unread,
Nov 15, 2006, 4:54:14 PM11/15/06
to


"Thierry Chappuis" <thi...@mujigka.ch> wrote in message news

I've got a system in place where "objects" implement "interfaces". So you
say

PORTABLE *port = isa(object, "portable");

if the function returns a pointer, object is portable, and has "weight",
"carry", "drop" and similar methods, accessible throught he function
pointer.

This is terribly inefficient, but it is game logic for an adventure game, so
the program has a tenth of a second or so to respond, which is ample for a
few string manipulations.
--
www.personal.leeds.ac.uk/~bgy1mm
freeware games to download.


Keith Thompson

unread,
Nov 15, 2006, 5:01:27 PM11/15/06
to

I think you mean "procedural" rather than "iterative".

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

CBFalconer

unread,
Nov 15, 2006, 5:06:27 PM11/15/06
to
Chris Dollin wrote:
> Cong Wang wrote:
>
>> Yeah. This is an interesting topic. In fact, C can NOT fully
>> support OOP like C++,
>
> It doesn't have syntactic support -- and that makes writing OO
> code a real bigger -- but you can do polymorphism/inheritance
> if you must; I think there's just enough room in the Standard
> to make the required machinery legal.
>
> Painful, but possible.
>
> Who knows. Maybe someone could write a translator from an OO
> language like C++ into pure C! Do you think that's possible?

That is how earlier C++ systems were implemented. Look up Cfront.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

Keith Thompson

unread,
Nov 15, 2006, 9:49:48 PM11/15/06
to
CBFalconer <cbfal...@yahoo.com> writes:
> Chris Dollin wrote:
>> Cong Wang wrote:
>>
>>> Yeah. This is an interesting topic. In fact, C can NOT fully
>>> support OOP like C++,
>>
>> It doesn't have syntactic support -- and that makes writing OO
>> code a real bigger -- but you can do polymorphism/inheritance
>> if you must; I think there's just enough room in the Standard
>> to make the required machinery legal.
>>
>> Painful, but possible.
>>
>> Who knows. Maybe someone could write a translator from an OO
>> language like C++ into pure C! Do you think that's possible?
>
> That is how earlier C++ systems were implemented. Look up Cfront.

Yeah, I think Chris knows that, as he strongly hinted in his signature:

| Chris "Cleft? Cright? Cback? Cside? I do like to be ..." Dollin

(Sorry if I'm spoiling the joke.)

Chris Torek

unread,
Nov 15, 2006, 11:18:49 PM11/15/06
to
In article <1163610431.8...@f16g2000cwb.googlegroups.com>
Thierry Chappuis <thi...@mujigka.ch> wrote, in part:

>struct Parent {
> int data;
> void (*print)(void);
>};
>
>struct Child {
> int data;
> void(*print)(void);
> int data2;
> int (*getData2)(void);
>};

I prefer to embed the "parent" structure into the "child":

struct Child {
struct Parent parent;
int data2;
int (*getData2)(void);
};

in this case. Going from child to parent is easy and cast-free:

struct Child *cp;
...
operate_on_parent(&cp->parent);

although going the other way (parent back to "known" child)
requires either a cast, or a trip through "void *".

(It might be nice if C99 had adopted (or perhaps C0X could adopt)
the Plan 9 extensions that make this work more cleanly.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.

Chris Dollin

unread,
Nov 16, 2006, 3:10:53 AM11/16/06
to
Keith Thompson wrote:

> raz...@gmail.com writes:
>> On Nov 15, 11:31 am, rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
>>> In article <1163605918.137964.21...@i42g2000cwa.googlegroups.com>,
>>>
>>> <raza...@gmail.com> wrote:
>>> >That's just one of the three requirements for an OO programming
>>> >language, encapsulation. The other two are inheritance and
>>> >polymorphismRequirements? Common characteristics perhaps.
>>
>> I guess 'requirements' was a strong word. The programming language
>> textbooks I've seen all list those three as necessary for OO languages.
>> The line between OO and iterative languages is much fuzzier than
>> between (I don't remember the exact terms) iterative, functional (e.g.
>> Lisp) and logical (e.g. Prolog).
>>
>> Colin K.
>
> I think you mean "procedural" rather than "iterative".

"imperative". Commands that change things. OO languages are, of
course, typically imperative. It's not a yes/no, there's more
of a range - Lisp is imperative, in that it /has/ state and changes
thereunto, but a lot of the language is to do with the functional
(as in having & using functions) part, so it supports a functional
style. A notable feature of the pure functional languages is that
they have /no/ state (and so no changes to it), which makes gluing
them into the imperative world interesting.

--
Chris "hantwig efferko VOOM!" Dollin
"Life is full of mysteries. Consider this one of them." Sinclair, /Babylon 5/

Chris Dollin

unread,
Nov 16, 2006, 3:14:03 AM11/16/06
to
CBFalconer wrote:

> Chris Dollin wrote:

>> Who knows. Maybe someone could write a translator from an OO
>> language like C++ into pure C! Do you think that's possible?
>
> That is how earlier C++ systems were implemented. Look up Cfront.

(fx:smirk)

--
Chris "bonus points to Keith Thompson" Dollin
The shortcuts are all full of people using them.

Roland Pibinger

unread,
Nov 16, 2006, 4:50:49 AM11/16/06
to
On 15 Nov 2006 02:28:02 -0800, "Thierry Chappuis" wrote:
>I'm interested in techniques used to program in an object-oriented way
>using the C ANSI language. I'm studying the GObject library and Laurent
>Deniau's OOPC framework published on his web site at
>http://ldeniau.web.cern.ch/ldeniau/html/oopc/oopc.html.

I bookmarked that link some time ago as an example how it should _not_
be done.

>The approach is
>very instructive. I know that I could do much of this stuff with e.g.
>C++, but the intellectual challenge of implementing these concepts with
>pure ANSI C is relevant to me.
>
>Are you aware of another approaches? Any experience in using such
>techniques in production code?

Many approaches use function pointers or hand-written vtables to
emulate polymorphism. But, AFAIK, they all hide the implementation
under a bunch of preprocessor macros to make it appear more 'object
oriented'. Essentially they create their own OO-language based on
macros which might be 'instructive' but also is rather uninviting for
most real world developers. See e.g.

http://www.ddj.com/184406396
http://www.pvv.ntnu.no/~hakonhal/main.cgi/c/classes
http://www.embedded.com/97/fe29712.htm

You find many links when you search for 'object-oriented programming
in C'.

Best wishes,
Roland Pibinger

Thierry Chappuis

unread,
Nov 16, 2006, 12:07:04 PM11/16/06
to

Roland Pibinger a écrit :

> Many approaches use function pointers or hand-written vtables to
> emulate polymorphism. But, AFAIK, they all hide the implementation
> under a bunch of preprocessor macros to make it appear more 'object
> oriented'. Essentially they create their own OO-language based on
> macros which might be 'instructive' but also is rather uninviting for
> most real world developers. See e.g.

Even with hand-written vtables, it is not a requirement to hide
implementation under macros and the resulting code does not seem to
heavy to handle and maintain. Do you think emulating inheritance and
polymorphism in this way is bad C practice?

Many thanks for the links. I'll study these differents approaches.

Best reagards

Thierry

Default User

unread,
Nov 16, 2006, 1:52:23 PM11/16/06
to
CBFalconer wrote:

> Chris Dollin wrote:

> > Who knows. Maybe someone could write a translator from an OO
> > language like C++ into pure C! Do you think that's possible?
>
> That is how earlier C++ systems were implemented. Look up Cfront.


I think, but wouldn't swear to it, that Comeau can provide a C++
compiler that produces C code.


Brian

Roland Pibinger

unread,
Nov 16, 2006, 4:28:52 PM11/16/06
to
On 16 Nov 2006 09:07:04 -0800, "Thierry Chappuis" wrote:
>Even with hand-written vtables, it is not a requirement to hide
>implementation under macros and the resulting code does not seem to
>heavy to handle and maintain. Do you think emulating inheritance and
>polymorphism in this way is bad C practice?

Not necessarily. Usability, as always, is the criterion. A solution
that avoids e.g. macros, void* parameters and casts required from
users has a higher probability of being accepted.

Best wishes,
Roland Pibinger

Thierry Chappuis

unread,
Nov 16, 2006, 6:12:13 PM11/16/06
to

Roland Pibinger a écrit :

Thank you for your valuable input.

Best wishes

Thierry

Laurent Deniau

unread,
Nov 17, 2006, 6:55:36 AM11/17/06
to
Roland Pibinger wrote:
> On 16 Nov 2006 09:07:04 -0800, "Thierry Chappuis" wrote:
>
>>Even with hand-written vtables, it is not a requirement to hide
>>implementation under macros and the resulting code does not seem to
>>heavy to handle and maintain. Do you think emulating inheritance and
>>polymorphism in this way is bad C practice?
>
>
> Not necessarily. Usability, as always, is the criterion. A solution
> that avoids e.g. macros

Why do you think that macros should be avoided?

> void* parameters and casts required from
> users has a higher probability of being accepted.

Agreed.

a+, ld.

Roland Pibinger

unread,
Nov 17, 2006, 9:29:55 AM11/17/06
to
On Fri, 17 Nov 2006 12:55:36 +0100, Laurent Deniau wrote:
>Roland Pibinger wrote:
>> On 16 Nov 2006 09:07:04 -0800, "Thierry Chappuis" wrote:
>>>Even with hand-written vtables, it is not a requirement to hide
>>>implementation under macros and the resulting code does not seem to
>>>heavy to handle and maintain. Do you think emulating inheritance and
>>>polymorphism in this way is bad C practice?
>>
>> Not necessarily. Usability, as always, is the criterion. A solution
>> that avoids e.g. macros
>
>Why do you think that macros should be avoided?

Macros usually obfuscate code more than clarify it. They make code
difficult to understand and write. Also error messages become harder
to decrypt. The following example hardly resembles procedural C code
any more:

#undef OBJECT
#define OBJECT person

BASEOBJECT_INTERFACE

char const* private(name);

BASEOBJECT_METHODS

void constMethod(print);

ENDOF_INTERFACE

CLASS_INTERFACE

t_person *const classMethod_(new) char const name[] __;
void method_(init) char const name[] __;
void method_(copy) t_person const*const per __;

ENDOF_INTERFACE

I expect from C code that it uses common C styles and idioms. IMO,
heavy use of the preprocessor is a means to avoid C programming.

Best regards,
Roland Pibinger

Thierry Chappuis

unread,
Nov 17, 2006, 9:56:42 AM11/17/06
to

Roland Pibinger a écrit :

I cannot agree with your point of view. In the above-mentioned example,
macros only hide the implementation of the object system. Such
low-level details are probably irrelevant to the user.

All the logic of the a program is implemented in standardized C code.
How about the use the presented person abstraction:

t_person *const per = person.new("Thierry");
sendMsg(per, print);
delete(per);

or
t_person *const per = person.new("Thierry");
per->__vptr->print(per);
delete(per);

For me it is C code: t_person is a structure or an union (in the
present case) and new points to a function responsible to create the
object. You can easily avoid the use of the macro sendMsg to call the
function print if you have some knowledge of the implementation (the
essentiel of the model can be understood from ooc.h). And you use
delete as you would use a wrapper free. What is not C in this code?

Thierry


> Best regards,
> Roland Pibinger

Laurent Deniau

unread,
Nov 17, 2006, 10:29:18 AM11/17/06
to

I partially agree. I have often said here or on fr.c.l.c that OOPC was
more a didactic paper to explain some facettes of C++. I have never used
it nor recommended to use it for professionnal developement.

After OOPC I developped during my free time, 3 other frameworks to do OO
in C (OOC-1.0, OOC-2.0 and COS = C Object System). I will not go into
the details and the history of this evolution over the past 6 years (if
you read french, you may have a look on many threads on this topic on
fr.c.l.c).

About the usage of the macros, and if you have a small knowledge of CLOS
and Objective-C syntax, what do you think of following working (but
incomplete) C99 code which uses COS macros to defines generics, class
and multimethods as generics specialisations, does it looks so different
from what we find in OO langages?

// sample of Generic.h
defgeneric(OBJ, gGetAt , (Container, Position));
defgeneric(OBJ, gGetAtIdx, (Container, (int)idx);
defgeneric(OBJ, gPutAt , (Container, Object, Position));
defgeneric(OBJ, gPutAtIdx, (Container, Object), (int)idx);

// sample of Generic.c
makgeneric(OBJ, gGetAt , (Container, Position));
makgeneric(OBJ, gPutAt , (Container, Object, Position));
makgeneric(OBJ, gPutAtIdx, (Container, Object), (int)idx);

// sample of Array.h
#include <cos/Collection.h>

defclass(Array, Collection)
int len;
OBJ *data;
endclass

// sample of Array.c
#include <cos/Array.h>

makclass(Array, Collection);

defmethod(OBJ, gPutAtIdx, (Array, Object), (int)idx)
{
if (0 > idx && idx >= self1->len) {
useclass(ExOutOfBound);
gThrow(gNewWithStr(ExOutOfBound, "invalid array index"));
}

if (self1->data[idx] != self2) {
if (self1->data[idx] != NIL)
gRelease(self1->data[idx]);

self1->data[idx] = gRetain(self2);
}

retmethod(self1);
}

// sample of main.c
#include <stdio.h>
#include <cos/cos.h>

useclass(Array,Integer,ExOutOfBound);

int main(void)
{
TRY
OBJ array = gNewWithSize(Array, 100);
OBJ value = gNewWithInt(Integer, 10);

gPutAtIdx(array, value, 15); // OK
gPutAtIdx(array, value, 200); // throw ExOutOfBound

CATCH(ExOutOfBound, ex)
fprintf(stderr, "exception %s thrown (%s,%i) and caught (%s,%i):"
"%s\n",
gNameStr(ex), ex_file, ex_line, __FILE__, __LINE__,
gReasonStr(ex));

FINALLY(ex)
gRelease(ex);
gRelease(array);
gRelease(value);
ENDTRY;
}

Note that generics are C functions (you can take a pointer to them) and
I use the convention (it's only a convention, not a requirement) to call
them gGeneric or vGeneric (variadic) to mark the difference of their
role with C functions.

a+, ld.

Laurent Deniau

unread,
Nov 17, 2006, 10:53:47 AM11/17/06
to
Laurent Deniau wrote:
>
> defmethod(OBJ, gPutAtIdx, (Array, Object), (int)idx)
> {
> if (0 > idx && idx >= self1->len) {
> useclass(ExOutOfBound);
> gThrow(gNewWithStr(ExOutOfBound, "invalid array index"));
> }
>
> if (self1->data[idx] != self2) {
> if (self1->data[idx] != NIL)
> gRelease(self1->data[idx]);
>
> self1->data[idx] = gRetain(self2);
> }
>
> retmethod(self1);
> }

Sorry this closing brace must be replaced by 'endmethod' and its
corresponding openning brace must be removed.

a+, ld.

E. Robert Tisdale

unread,
Nov 17, 2006, 1:53:58 PM11/17/06
to
Thierry Chappuis wrote:

> I'm interested in techniques used to program in an object-oriented way
> using the C ANSI language. I'm studying the GObject library and Laurent
> Deniau's OOPC framework published on his web site at

> http://ldeniau.web.cern.ch/ldeniau/html/oopc/oopc.html. The approach is


> very instructive. I know that I could do much of this stuff with e.g.
> C++, but the intellectual challenge of implementing these concepts with
> pure ANSI C is relevant to me.
>
> Are you aware of another approaches? Any experience in using such

> techniques in production code? The use of GObject seems to be well
> implemented in the GNOME world, but I didn't find much about Laurent
> Deniau's OOPC. Have you some comments about the strengths and drawbacks
> of such techniques?

Please find attached a C implementation
of Bjarne Stroustrup's famous Shape class.

C is not an object oriented programming language
but you can write object oriented programs in C
including programs that implement run-time polymorphism.
The fprintf function on type *FILE is an example.
You don't need a language translator or a special library.

A program is not an object oriented programming language
just because it is written in an object oriented programming language.
All the popular object oriented programming languages are
procedural programming languages first.
An object oriented program must actually use
the object oriented features of the language.
Object oriented programming is first of all a programming style.

The problem with C is that it does not directly support features
such as inheritance and run-time polymorphism. Good C programmers
have always used an object oriented programming style
but implementing object oriented programs in C is problematic --
tedious and error prone. The C++ programming language provides
direct support for object oriented programming
so it is much easier and more reliable.

Archive

Roland Pibinger

unread,
Nov 17, 2006, 3:30:25 PM11/17/06
to
On Fri, 17 Nov 2006 10:53:58 -0800, "E. Robert Tisdale" wrote:
>Thierry Chappuis wrote:
>> I'm interested in techniques used to program in an object-oriented way
>> using the C ANSI language. of such techniques?

>
>Please find attached a C implementation
>of Bjarne Stroustrup's famous Shape class.

Your approach is similar to the results of my experiments with OO in
C. You can increase encapsulation when you only forward declare your
structs (e.g. struct Shape) in the header files. Also some functions
(e.g. actualShape_draw) can be removed form the header and made
'private', i.e. static, in the respecive *.c file.

Best regards,
Roland Pibinger

matevzb

unread,
Nov 17, 2006, 3:40:34 PM11/17/06
to
There's a book/paper called "Object-Oriented Programming with ANSI-C"
by Axel-Tobias Schreiner, available as a PDF at
http://www.planetpdf.com/codecuts/pdfs/ooc.pdf. It explores this area
to a great extend and I'd really recommend it.

--
WYCIWYG - what you C is what you get

Roland Pibinger

unread,
Nov 17, 2006, 4:24:59 PM11/17/06
to
On 17 Nov 2006 12:40:34 -0800, "matevzb" <mat...@gmail.com> wrote:
>There's a book/paper called "Object-Oriented Programming with ANSI-C"
>by Axel-Tobias Schreiner, available as a PDF at
>http://www.planetpdf.com/codecuts/pdfs/ooc.pdf. It explores this area
>to a great extend and I'd really recommend it.

It's awful! IIRC, it needs AWK as preprocessor and uses mostly untyped
void* pointers. IIRC, the book was never published in English because
it found no publisher. Guess why.

Regards,
Roland Pibinger

matevzb

unread,
Nov 17, 2006, 4:43:36 PM11/17/06
to
> It's awful! IIRC, it needs AWK as preprocessor and uses mostly untyped
> void* pointers.
That was just my opinion and you don't have to agree. I found it
useful, as it demonstrates what can be done in C. Void pointers can be
dangerous, but then again, what would C be without them? =)
(AWK is optional, depending on what you want to do)

> IIRC, the book was never published in English because
> it found no publisher. Guess why.

Many books haven't been published in English. That doesn't mean they're
bad books. (same goes for the authors)

Chris Thomasson

unread,
Nov 17, 2006, 6:07:27 PM11/17/06
to
"Thierry Chappuis" <thi...@mujigka.ch> wrote in message
news:1163586482....@i42g2000cwa.googlegroups.com...
> Hi,

>
> I'm interested in techniques used to program in an object-oriented way
> using the C ANSI language. I'm studying the GObject library and Laurent
> Deniau's OOPC framework published on his web site at
> http://ldeniau.web.cern.ch/ldeniau/html/oopc/oopc.html. The approach is
> very instructive. I know that I could do much of this stuff with e.g.
> C++, but the intellectual challenge of implementing these concepts with
> pure ANSI C is relevant to me.
>
> Are you aware of another approaches?

[...]

Check this crap out:

http://groups.google.com/group/comp.lang.c/msg/6cf857051ca4029b


;^)


E. Robert Tisdale

unread,
Nov 17, 2006, 7:37:35 PM11/17/06
to
Roland Pibinger wrote:

> Your approach is similar to the results of my experiments with OO in
> C. You can increase encapsulation when you only forward declare your
> structs (e.g. struct Shape) in the header files.

Unfortunately, your approach precludes automatic function inlining.

> Also some functions (e.g. actualShape_draw) can be removed form the header
> and made 'private', i.e. static, in the respecive *.c file.

This would preclude any explicit call to function actualShape_draw.
An optimizing C++ compiler will elide the virtual {messenger} function
and call the actual function directly
if it can determine the actual type at compile time.

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----

CBFalconer

unread,
Nov 17, 2006, 9:24:02 PM11/17/06
to
"E. Robert Tisdale" wrote:
>
... snip ...

>
> This would preclude any explicit call to function actualShape_draw.
> An optimizing C++ compiler will elide the virtual {messenger}
> function and call the actual function directly if it can determine
> the actual type at compile time.

This is c.l.c. comp.lang.c++ is thataway ------>

Thierry Chappuis

unread,
Nov 18, 2006, 4:32:54 AM11/18/06
to
matevzb a écrit :

Hi,

The Schreiner's approach uses heavy awk preprocessing, and too many
generic (void *) pointers. It is not the most convincing paper I've
read on the subject.

Thank you for your contribution

Thierry

Thierry Chappuis

unread,
Nov 18, 2006, 4:37:14 AM11/18/06
to

Chris Thomasson a écrit :


Thank you for the link! Bookmarked!

Thierry

Roland Pibinger

unread,
Nov 18, 2006, 6:07:35 AM11/18/06
to
On Fri, 17 Nov 2006 16:37:35 -0800, "E. Robert Tisdale" wrote:
>Roland Pibinger wrote:
>> Your approach is similar to the results of my experiments with OO in
>> C. You can increase encapsulation when you only forward declare your
>> structs (e.g. struct Shape) in the header files.
>
>Unfortunately, your approach precludes automatic function inlining.

No encapsulation means no OO. You can't have both at the same time :-)

>> Also some functions (e.g. actualShape_draw) can be removed form the header
>> and made 'private', i.e. static, in the respecive *.c file.
>
>This would preclude any explicit call to function actualShape_draw.
>An optimizing C++ compiler will elide the virtual {messenger} function
>and call the actual function directly if it can determine the actual
>type at compile time.

But isn't polymorphism the point of the whole exercise?

Best regards,
Roland Pibinger

E. Robert Tisdale

unread,
Nov 18, 2006, 2:43:06 PM11/18/06
to
Roland Pibinger wrote;

> On Fri, 17 Nov 2006 16:37:35 -0800, "E. Robert Tisdale" wrote:
>> Roland Pibinger wrote:
>>> Your approach is similar to the results of my experiments with OO in
>>> C. You can increase encapsulation when you only forward declare your
>>> structs (e.g. struct Shape) in the header files.
>> Unfortunately, your approach precludes automatic function inlining.
>
> No encapsulation means no OO. You can't have both at the same time :-)

You probably meant "data hiding".
The C computer programming language allows you to encapsulate data
[in a struct] but it doesn't support data hiding at all.
Using an opaque data types
(publishing a struct declaration without publishing it's definition)
precludes some compile time optimizations.

>>> Also some functions (e.g. actualShape_draw) can be removed form the header
>>> and made 'private', i.e. static, in the respecive *.c file.
>> This would preclude any explicit call to function actualShape_draw.
>> An optimizing C++ compiler will elide the virtual {messenger} function
>> and call the actual function directly if it can determine the actual
>> type at compile time.
>
> But isn't polymorphism the point of the whole exercise?

Yes, but there is no reason
why that should preclude non-polymorphic applications.

Keith Thompson

unread,
Nov 18, 2006, 3:32:41 PM11/18/06
to
"E. Robert Tisdale" <ed...@netwood.net> writes:
[...]

> You probably meant "data hiding".
> The C computer programming language allows you to encapsulate data
> [in a struct] but it doesn't support data hiding at all.

It doesn't? At all?

> Using an opaque data types
> (publishing a struct declaration without publishing it's definition)
> precludes some compile time optimizations.

Ah, so it *does* support data hiding.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Richard Tobin

unread,
Nov 18, 2006, 6:34:34 PM11/18/06
to
In article <455ee7c7...@news.utanet.at>,
Roland Pibinger <rpb...@yahoo.com> wrote:

>No encapsulation means no OO.

No encapsulation mean no points from the B&D end of the OO cabal, but
who cares?

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.

Chris Thomasson

unread,
Nov 18, 2006, 7:09:46 PM11/18/06
to
"Thierry Chappuis" <thi...@mujigka.ch> wrote in message
news:1163842634.2...@h54g2000cwb.googlegroups.com...

Chris Thomasson a écrit :
>>"Thierry Chappuis" <thi...@mujigka.ch> wrote in message
>> news:1163586482....@i42g2000cwa.googlegroups.com...
>> Hi,
>> I'm interested in techniques used to program in an object-oriented way
>> using the C ANSI language.

[...]

>> Are you aware of another approaches?
>
> [...]
>
>>> Check this crap out:
>>>
>>> http://groups.google.com/group/comp.lang.c/msg/6cf857051ca4029b

"Thierry Chappuis"


>>>> Thank you for the link! Bookmarked!

No problem... The technique works very well, IMHO. Its a quick, clear and
clean method for supporting basic OO programming in pure ANSI C. I like it
better than C++ in some respects; I am a C/Assembly Language programmer at
heart...

;^)


Roland Pibinger

unread,
Nov 19, 2006, 7:16:08 AM11/19/06
to
On Sat, 18 Nov 2006 20:32:41 GMT, Keith Thompson wrote:
>"E. Robert Tisdale" writes:
>[...]
>> You probably meant "data hiding".
>> The C computer programming language allows you to encapsulate data
>> [in a struct] but it doesn't support data hiding at all.

There have been many discussions whether encapsulation and information
hiding are the same or whether one is a means for the other. Let's
assume we mean that data should not be accessible from the 'outside'.

>It doesn't? At all?
>
>> Using an opaque data types
>> (publishing a struct declaration without publishing it's definition)
>> precludes some compile time optimizations.
>
>Ah, so it *does* support data hiding.

I've always wondered why C programmers often unnecessarily give up
encapsulation. You can frequently see code like the following:

struct my_struct {
// some data
};
typedef struct my_struct my_struct;

my_struct* init (int i);
int do_something (my_struct* p, int n, float f);
// more functions
void cleanup (my_struct* p);

In the above example the my_struct definition in the header file is
unnecessary, a forward declaration (struct my_struct;) is sufficient.
The user not only gets access to 'private' data but also the my_struct
data become part of the published interface. This means that future
releases of the code cannot alter that data any more (not even
rearrange them) without potentially breaking existing code. Sometimes
the (generous) use of macros prevents encapsulation but in many cases
lack of encapsulation seems to be just an oversight of the programmer.

Best regards,
Roland Pibinger

E. Robert Tisdale

unread,
Nov 19, 2006, 4:24:09 PM11/19/06
to
Roland Pibinger wrote:

> I've always wondered
> why C programmers often unnecessarily give up encapsulation.
> You can frequently see code like the following:
>
> struct my_struct {
> // some data
> };
> typedef struct my_struct my_struct;
>
> my_struct* init (int i);
> int do_something (my_struct* p, int n, float f);
> // more functions
> void cleanup (my_struct* p);
>

> In the above example,
> the my_struct definition in the header file is unnecessary.
> A forward declaration (struct my_struct;) is sufficient.
> The user not only gets access to 'private' data but, also,


> the my_struct data become part of the published interface.
> This means that future releases of the code cannot alter that data any more
> (not even rearrange them) without potentially breaking existing code.

> Sometimes the (generous) use of macros prevents encapsulation but, in many cases,


> lack of encapsulation seems to be just an oversight of the programmer.

This is poor programming practice.
It compels the programmer to create an uninitialized variable.

It would be better to define a pseudo-constructor

inline
my_struct my_struct_create(int i) {
my_struct value;
// initialize value
return value;
}

and a destructor

inline
void my_struct_destroy(const my_struct* p) {
}


which you might use like this

const
my_struct t = my_struct(13);

// . . .

my_struct_destroy(&t);

Function do_something should not modify *p
and should be declared as

inline
int do_something (const my_struct* p, int n, float f);

If the object really is a container,
you must provide methods that permit users to modify them.

This is a lot safer and more reliable than the methods
that you have suggested. It also allows the C compiler
to inline the functions to improve performance and efficiency.


The C computer programming language does not support data hiding.
Opaque data types may preclude certain optimizations.

Chris Thomasson

unread,
Nov 19, 2006, 7:14:51 PM11/19/06
to
"Roland Pibinger" <rpb...@yahoo.com> wrote in message
news:45603e4a...@news.utanet.at...

> On Sat, 18 Nov 2006 20:32:41 GMT, Keith Thompson wrote:
>>"E. Robert Tisdale" writes:
>>[...]
>>> You probably meant "data hiding".
>>> The C computer programming language allows you to encapsulate data
>>> [in a struct] but it doesn't support data hiding at all.
>
> There have been many discussions whether encapsulation and information
> hiding are the same or whether one is a means for the other. Let's
> assume we mean that data should not be accessible from the 'outside'.
>
>>It doesn't? At all?
>>
>>> Using an opaque data types
>>> (publishing a struct declaration without publishing it's definition)
>>> precludes some compile time optimizations.
>>
>>Ah, so it *does* support data hiding.
>
> I've always wondered why C programmers often unnecessarily give up
> encapsulation. You can frequently see code like the following:
>
> struct my_struct {
> // some data
> };
> typedef struct my_struct my_struct;

[...]


header
----------

typedef struct mystuff_s *mystuff_t;

extern int mystuff_alloc(mystuff_t*, /* config */);
/* whatever */


source
----------

#include "header"
struct mystuff_s {
/* whatever */
};


int mystuff_alloc(mystuff_t *_pthis, /* config */) {
if (_pthis && /* config is valid */) {
mystuff_t _this = malloc(sizeof(*_this));
if (_this) {
if (/* config of '_this' succeeds */) {
*_pthis = _this;
return 1;
}
}
free(_this);
}

return 0;
}

/* whatever */

It's that simple to hide data-structures that are too sensitive to be in the
hands of a user... Of course "they" can disassemble your code and figure
things out real good, then create a definition of your data-structure(s) for
themselves... Nothing is "crowbar" proof here... Its as simple as following
your pointer and recording all of the offsets from every load/store that
deals with it...

;^)


0 new messages