[HN Gopher] C Object Oriented Programming (2014)
___________________________________________________________________
C Object Oriented Programming (2014)
Author : sergiogdr
Score : 36 points
Date : 2023-12-20 12:46 UTC (1 days ago)
(HTM) web link (nullprogram.com)
(TXT) w3m dump (nullprogram.com)
| naitgacem wrote:
| Excellent writeup and straight to the point. As the author
| demonstrated one can get quite a lot of OOP constructs using C
| primitives.
|
| what seems to be impossible to implement (as least to me) was
| something like interfaces, a way to decouple in a way such that
| high level functions don't need to know about the low level
| building blocks.
| skribanto wrote:
| You can approximate it by maintaining some kind of vtable, but
| it can get messy, especially if you need to implement multiple
| traits/interfaces.
| pjmlp wrote:
| We used to have books about it, and stuff like COM, SOM, CORBA
| also support C, which is exactly what you're referring to.
|
| Regarding books, here is one from 1993,
| https://www.mclibre.org/descargar/docs/libros/ooc-ats.pdf
| vkazanov wrote:
| Classic..!
|
| I wonder how it feels now, 20 years after reading it for the
| first time. I remember how revelatory it felt.
| miuramxciii wrote:
| Yes, You can. The entire Linux device interface, to name just
| one example, if full of interfaces. The way to accomplish this
| is via pointer to functions, and to have it as an object, have
| these pointer to functions grouped in a struct. GTK/Glib is
| notably full of these interfaces too.
| spaceywilly wrote:
| Yup. In a past job I did a lot of work writing ALSA drivers
| for custom souncards. The ALSA interface is a good example of
| this. They provide an API app developers can use to do sound
| stuff (change the volume, for example). In your sound card
| driver you provide an implementation of the API to do
| whatever changing the volume means for your particular
| hardware (in my case sending an i2c message to a digital
| potentiometer).
|
| https://www.kernel.org/doc/html/v4.14/sound/kernel-
| api/alsa-...
| dboreham wrote:
| Um, this is how software was built in the olden days. C++
| literally began as "we could write a preprocessor to automate
| the tricks everyone uses to implement polymorphism in C"
| (CFront). And prior to that, the same tricks were used in
| assembly language programming. So this article has recreated
| the history of OOP, which was to create tooling to better
| support programming techniques already widely used. It wasn't
| some religion invented by the priests and sent forth on
| tablets, although due to humans loving them some cult, it
| became that eventually.
| dceddia wrote:
| One thing to look at is ffmpeg in its encoders and decoders. At
| the bottom of the file there's a struct with pointers to
| functions (among other things). Anything that wants to do
| decoding can just call init(), decode(), close() on an AVCodec
| and the internal functions do whatever they need to do. Here's
| one from h264.c: AVCodec ff_h264_decoder = {
| .name = "h264", .type = AVMEDIA_TYPE_VIDEO,
| .init = ff_h264_decode_init, .close =
| h264_decode_end, .decode = h264_decode_frame,
| ... more fields ... };
| nanolith wrote:
| One advantage to this approach is that there is less compiler
| magic going on. I use a similar approach, but I prefer using type
| safe upcasting or model checked downcasting via inline functions
| or explicit references to base members, instead of direct C style
| casting.
|
| This also makes it easier to develop a uniform resource
| management strategy with allocator abstraction. Being able to
| easily switch between tuned bucket, pool, or bump allocation
| strategies can do wonders for optimization.
|
| It's possible to model check that downcasting is done correctly,
| by adding support for performing type checks at analysis time. In
| this case, a type variable is added to the base type that can be
| compared before casting. Since this is an analysis only variable,
| it can be wrapped in a macro so that it is eliminated during
| normal compilation. Static assertions checked by the model
| checker during analysis time may need to be refactored to extract
| the type information as a proof obligation made by the caller.
| This technique actually works quite well using open source model
| checkers like CBMC.
|
| Either way, some C OOP is not only useful to provide some
| optimization knobs, but it's also quite useful for introducing
| annotations that can help to formally verify C but that don't
| actually incur any runtime overhead.
| o11c wrote:
| Hmm, I don't have much to disagree with for this link, unlike
| many things from that site.
|
| One minor point - the method implementations should _not_ be
| `static`, so that you can support further subclassing and reuse
| the base class implementations.
|
| Note that to support both virtual and non-virtual method binding,
| the dispatcher also needs to be exported (with the same
| signature). This is already the case in the linked code but a
| point isn't made of it; it can be tempting to abuse `inline` but
| remember that is primarily about visibility [1].
|
| It also doesn't mention how to implement `dynamic_cast`
| (practically mandatory for multimethod-like things), which can be
| quite tricky, especially in the multiple-inheritance case and/or
| when you don't know all the subclasses ahead of time and/or when
| you have classes used in across shared libraries. There are cases
| where you really do need multiple vtables.
|
| Virtual inheritance, despite its uses, is probably a mistake so
| it's fine that it ignores that.
|
| [1]: https://stackoverflow.com/a/51229603/1405588
___________________________________________________________________
(page generated 2023-12-21 23:00 UTC)