[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)