Live data from Hacker News

Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

leandromoreira.com

51–60 of 131 posts

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#51
post #50

For the record, this design pattern is called a virtual method table, or vtable. I'm surprised that this article never mentioned the term. C++ programmers will know this pattern from the `virtual` keyword.

I've noticed many large C projects resort to these sorts of OOP-like patterns to manage the complexity of the design and size of the code base. But I'm not aware of any one standard way of doing this in C. It seems C++ standardized a lot of these concepts, or C++ developers adopted standard patterns somehow.

and C++ also supports optimizing them, especially when you use `final` keyword and LTO which is able to devirtualize at the scale of a whole program.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#52

Who would have thought that OOP could be useful!

This is not oop but polymorphism that is useful. And various forms of polymorphism are used in all kinds of programming paradigms. Also, this is a nice way to get the damn banana without getting lost in the jungle.

polymorphism used that way is 100% the most traditional OOP possible ever

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#53
post #46
post #35

Earlier quoted context omitted.

Every language has inconsistencies, and C is not stranger to that. Much of c++’s baggage is due to C and you carry the same weight. That’s not to say that initialization isn’t broken in C++, but just like many features in many languages (off the top of my head in C - strcpy, sprintf, ctime are like hand grenades with the pin pre pulled for you) don’t use them. There’s a subset of C++17 that to me solves so many issue…

You could write this in C, no? { int val; if (getFoo(&val)) { ... }} Both ways of expressing this are weird, but stating that this can't be achieved with C is dishonest in my opinion.

it's not that weird to explicitly limit the scope of certain variables that logically belong together.

But i agree the C++ if(init;cond) thing was new to me.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#54

This is an excellent pattern in C. The Dovecot mail server has many fine examples of the style as well e.g. struct dict dict_driver_ldap = { .name = "ldap", .v = { .init = ldap_dict_init, .deinit = ldap_dict_deinit, .wait = ldap_dict_wait, .lookup = ldap_dict_lookup, .lookup_async = ldap_dict_lookup_async, .switch_ioloop = ldap_dict_switch_ioloop, } }; defines the virtual function table for the LDAP module, and any o…

Reminds me of Apple’s CoreFoundation.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#55
post #50

Earlier quoted context omitted.

I've noticed many large C projects resort to these sorts of OOP-like patterns to manage the complexity of the design and size of the code base. But I'm not aware of any one standard way of doing this in C. It seems C++ standardized a lot of these concepts, or C++ developers adopted standard patterns somehow.

and C++ also supports optimizing them, especially when you use `final` keyword and LTO which is able to devirtualize at the scale of a whole program.

Interesting, in Rust those optimizations are more implicit since there's no "final" keyword when you use dynamic dispatch via trait objects. + you also got LTO.

I wonder if there are many cases where C++ will devirtualize and Rust won't.

But then again Rust devs are more likely to use static dispatch via generics if performance is critical.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#56

Earlier quoted context omitted.

This is not oop but polymorphism that is useful. And various forms of polymorphism are used in all kinds of programming paradigms. Also, this is a nice way to get the damn banana without getting lost in the jungle.

polymorphism used that way is 100% the most traditional OOP possible ever

Yes, a similar approach to polymorhpism is supertypical for popular OOP-focused languages, along with other concepts.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#57
post #46
post #35

Earlier quoted context omitted.

Every language has inconsistencies, and C is not stranger to that. Much of c++’s baggage is due to C and you carry the same weight. That’s not to say that initialization isn’t broken in C++, but just like many features in many languages (off the top of my head in C - strcpy, sprintf, ctime are like hand grenades with the pin pre pulled for you) don’t use them. There’s a subset of C++17 that to me solves so many issue…

You could write this in C, no? { int val; if (getFoo(&val)) { ... }} Both ways of expressing this are weird, but stating that this can't be achieved with C is dishonest in my opinion.

If I reformat this,

    {
        int val; 
        if (getFoo(&val)) {
    
        }
        printf("%d", val);
    }
The bug is still possible, as you've introduced an extra scope that doesn't exist in the C++ version.

Also, this was one example. There are plenty of other examples.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#58

This is an excellent pattern in C. The Dovecot mail server has many fine examples of the style as well e.g. struct dict dict_driver_ldap = { .name = "ldap", .v = { .init = ldap_dict_init, .deinit = ldap_dict_deinit, .wait = ldap_dict_wait, .lookup = ldap_dict_lookup, .lookup_async = ldap_dict_lookup_async, .switch_ioloop = ldap_dict_switch_ioloop, } }; defines the virtual function table for the LDAP module, and any o…

So does the good old Quake 2 rendering API. The game exported a bunch of functions to the renderer via refimport_t and the renderer in return provided functions via refexport_t. The only visible symbol in a rendering DLL is GetRefAPI_t: https://github.com/id-Software/Quake-2/blob/master/client/re... I remember being impressed by this approach, so I shamelessly copied it for my programming game: https://github.com/div…

I somehow suspect that the reason why Quake2 does this lies in the legacy of Quake1 written in DJGPP. DJGPP supports dynamicaly loaded libraries (although the API is technically unsupported and internal-only), but does not have any kind of dynamic linker, thus passing around pair of such structs during library initialization is the only way to make that work.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#59
post #3

> The interface type in golang is much more powerful than Java’s similar construct because its definition is totally disconnected from the implementation and vice versa. We could even make each codec a ReadWriter and use it all around. This paragraph completely derailed me — I’m not familiar with golang, but `interface` in Java is like `@protocol` in Objective-C — it defines an interface without an implementation for…

The difference between Go and Java is that in Go a type need not declare its adherence to an interface up front—any type that has methods of appropriate names and signatures is considered to implement the interface, even if its designers were not aware of the interface’s existence. (This involves a small bit of dynamism in the runtime; easily cached, though, as the set of methods of a given type and the set of all in…

I don’t agree it’s a structural VS nominal difference. Typescript is structural, but it does have the “implements” keyword.

Which makes a million times more sense to me, because realistically when do you ever have a structure that usefully implements an interface without being aware of it?? The common use-case is to implement an existing interface (in which case might as well enforce adherence to the interface at declaration point), not to plug an implementation into an unrelated functionality that happens to expect the right interface.

Re: Exploring Polymorphism in C: Lessons from Linux and FFmpeg's Code Design (2019)

#60
post #45

Earlier quoted context omitted.

it actually isn't https://www.stroustrup.com/bs_faq.html#C-is-subset

Do you usually post links without reading them? "In the strict mathematical sense, C isn't a subset of C++. There are programs that are valid C but not valid C++ and even a few ways of writing code that has a different meaning in C and C++. However, C++ supports every programming technique supported by C. Every C program can be written in essentially the same way in C++ with the same run-time and space efficiency. It…

> For example, every example in Kernighan & Ritchie: "The C Programming Language (2nd Edition)" is also a C++ program. "

That is rather dated, they do things like explicitly cast the void* pointer returned by malloc, but point out in the appendix that ANSI C dropped the cast requirement for pointer conversions involving void, C++ does not allow implicit void conversions to this day.

Post reply on HN