You know what gstreamer does, right? It's a dynamic multimedia framework - you give it pipeline defined by string, like:

ximagesrc display_name=:1 ! video/x-raw,framerate=20/1 ! videoscale ! videoconvert ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast ! rtph264pay ! udpsink host=127.0.0.1 port=5000

and it automatically loads .so files, creates all those components and connects them to each other. Super handy for all sorts of fun audio/video processing.

So all that C ceremony is required because user _should_ be able to say "ximagesrc display_name=:1", and possibly dynamically change this attribute to something else via script command (because a lot of time gstreamer is embedded in other apps).

So if you know how to achieve the same without trying to "shoehorn an OOP system into C", do let me know. But I bet whatever solution you came up with would be very close to what GStreamer ended up doing, if not even more complex.

(Unless what you are trying to say is: "If problem's most-efficient representation is OOP-like, don't use it with C because C is for simpler problems only. Use complex languages for complex tasks." If that's the case, I fully agree)

> and it automatically loads .so files, creates all those components and connects them to each other. Super handy for all sorts of fun audio/video processing.

I created a quite similar OOP system for C around 1995 (as I guess did most programmers at that time who were fascinated by Objective-C), classes were implemented in DLLs and were loaded on demand, classes were objects themselves, the tree of class objects could be inspected (e.g. runtime-type-information and -reflection), and the whole system was serializable - this was for a PC game (https://en.wikipedia.org/wiki/Urban_Assault).

It looked like a neat thing at the time, but nothing a couple of structs with function pointers or a switch-case message dispatcher wouldn't be able to do just as well, definitely not something that should be the base for more than one product, and most definitely nothing that should have survived the OOP hype of the 90's ;)

This kind of automatic property serialization/deserialization, however, has traditionally been a sore spot for C++ as well.

You can do it, but you will have to either repeat yourself at least a little, use some very ugly macros, or use a code generator.

And many of those ugly macro tricks work in C as well. So do code generators.

That said, as C++ has added features, this type of metaprogramming has gotten easier and easier, and more and more distinct from C. This culminates in C++26 reflection which will finally make it possible to just define a struct and then automatically generate serialization/deserialization for it, without hacks. Once reflection is implemented and widely adopted, then I will agree with you that this should be 1 or 2 lines in a well-structured C++ app.