Object-oriented programming in standard ANSI C

T

Thierry Chappuis

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
 
C

Cong Wang

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.
 
R

razael1

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.
 
S

santosh

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.
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).
 
F

Fred Kleinschmidt

Thierry Chappuis said:
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

Look at the way a Widget is defined in the Unix Xt or Motif libraries.
 
C

Chris Dollin

Cong said:
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?
 
S

santosh

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?
 
R

Richard Tobin

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
 
J

Jean-Marc Bourguet

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,
 
T

Thierry Chappuis

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
 
W

William Hughes

Chris said:
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
 
R

razael1

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.
 
M

Malcolm

Thierry Chappuis said:
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?
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.
 
K

Keith Thompson

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".
 
C

CBFalconer

Chris said:
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.
 
K

Keith Thompson

CBFalconer said:
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.)
 
C

Chris Torek

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.)
 
C

Chris Dollin

Keith said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top