News for hackers. Stuff that matters.
Re:OOP in C by vidarh on Sunday January 08, 2023 @06:16AM (#34298135)
Polymorphism in C is trivial: You use a vtable - a struct of method pointers. Same approach most languages with "simple" method resolution mechanisms, like e.g C++, uses under the hood.

You don't need macros. You either call via the vtable, or you write a wrapper per interface per message.

E.g.

   int string_length(void * self) { return (object *)self->class.vtable[STRING_LENGTH_SLOT](self) }
Such wrappers are fairly trivial to generate if you don't want to handwrite them.

If you want complex inheritance patterns, you might benefit from one more level of indirection, see e.g. Protocol Extension: A Technique for Structuring Large Extensible Software-Systems (M. Franz, 1995). That paper is for Oberon, but it's easily translatable to C - did that way back.

Upside is it let's you group functionality in interfaces with less of an explosion in vtable size, downside is the cost of one extra pointer indirection.

Re:OOP in C by throw_m239339 on Sunday January 08, 2023 @06:39AM (#34298258)
> You don't need macros. You either call via the vtable, or you write a wrapper per interface per message.

I know, thus the /s for sarcasms.

> Such wrappers are fairly trivial to generate if you don't want to handwrite them.

It's fairly irrelevant to my point, which is that C structs aren't equivalent to Java classes in anyway.

Of course you can implement OO is C, I've done enough GObject in my life to know how horrible it is to use in practice.

Re:OOP in C by vidarh on Sunday January 08, 2023 @06:46AM (#34298299)
They only way they aren't is that the class pointer is hidden from the user.
Re:OOP in C by zabzonk on Sunday January 08, 2023 @06:27AM (#34298192)
what does an "object" look like? how do i derive from it?
Re:OOP in C by vidarh on Sunday January 08, 2023 @06:45AM (#34298290)
Any struct. Only requirement would be that the first element can be casted to a point to a class object containing the vtable. I'ved edited to fix the casting so it actually compiles, and to use a void * in the argument list, as is what you'd actually usually do.
Re:OOP in C by Inviz on Sunday January 08, 2023 @06:45AM (#34298293)
generic base type struct
Re:OOP in C by rramadass on Sunday January 08, 2023 @06:50AM (#34298321)
Easy; a subclass struct embeds the superclass struct as its first member.

Simple example here: https://embeddedgurus.com/state-space/2008/01/object-based-p...

Lots more here: https://stackoverflow.com/questions/351733/how-would-one-wri...

Re:OOP in C by codr7 on Sunday January 08, 2023 @09:44AM (#34299486)
Having spent quite some time down that rabbit hole back in the days, I'd definitely recommend against pushing C in that direction. Few people love GObject, for good reasons.

Embedding combined with the container_of-macro [0] is a much more constructive approach from my experience.

[0] https://stackoverflow.com/questions/15832301/understanding-c...

Re:OOP in C by wheelerof4te on Sunday January 08, 2023 @06:43AM (#34298281)
Nothing in your example looks or reads as trivial. That is a gross perversion of a simple procedural language.
Re:OOP in C by vidarh on Sunday January 08, 2023 @06:47AM (#34298305)
Trivial to a C developer then. This has been typical of C code for literally decades. The only thing that sucks there is writing wrappers, but it's easy to generate them.

From a user point of view you end up doing things like:

  string * str = string_new();
  int len = string_length(str);
So it looks just like most other typical C code using prefixes per interface and passing pointers to structs around.

In practice, like in C++, you'd tend to only actually use the vtable approach for those things which you actually need to be able to override based on type, which tends to be rare.

Another approach is to use messages instead, and a call a generic message handler. E.g. "ob->call(MSG_TYPE, ... arguments)" and just have a pointer to a message handler function as the first pointer in your objects. It's more flexible, but slower.

Re:OOP in C by wheelerof4te on Sunday January 08, 2023 @06:53AM (#34298328)
"int string_length(void * self) { return ((int ()(void ))((object *)self)->class->vtable[STRING_LENGTH_SLOT])(self);"

Oh.My.God.

At this point, you might as well be using Java.

Re:OOP in C by vidarh on Sunday January 08, 2023 @07:07AM (#34298406)
If you're writing C, you'll be writing much worse than that on a regular basis. There's a reason I rarely use C any more.

But of course if you're going to reimplement OO from scratch in C you will see the entire machinery laid bare. You're only doing it in the first place either because you're committed to using C for whatever reason, or to understand OO implementation strategies.

Re:OOP in C by vidarh on Sunday January 08, 2023 @09:41AM (#34299461)
Replying to myself to leave this here, since it's vaguely related. If anyone really want to have nightmares about OO'ish concepts in C, here is a few different ways to implement closures in C, going from relatively straightforward, to (unportable) runtime generation of assembler thunks:

https://hokstad.com/how-to-implement-closures

Re:OOP in C by rramadass on Sunday January 08, 2023 @07:02AM (#34298380)
You are just being glib here.

If you want simpler models see my other comments in this thread.

Re:OOP in C by Shorel on Sunday January 08, 2023 @09:01AM (#34299149)
Or C++

/gasp