Live data from Hacker News

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

leandromoreira.com

31–40 of 131 posts

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

#31
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…

interfaces in Go are structural. Interfaces in Java are nominal and require immediate declaration of intent to implement at type definition.

Shouldn’t this be named phenomenal rather than structural? In both cases there is a structure assumed, but one is implicitly inferred while the other one is explicitly required.

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

#32
post #27

Earlier quoted context omitted.

You can take it a step further: - instead of setting the same function pointers on structs over and over again, point to a shared (singleton) struct named "vtable" which keeps track of all function pointers for this "type" of structs - create a factory function that allocates memory for the struct, initializes fields ("vtable" included), let's call it a "constructor" - make sure all function signatures in the shared…

Is this satire? That’s almost exactly the C++ way.

It’s not satire, it’s how you do full OO in plain C.

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

#33

Earlier quoted context omitted.

Is this satire? That’s almost exactly the C++ way.

It’s not satire, it’s how you do full OO in plain C.

It's overloaded - it is satire, but also, it isn't.

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

#34

Earlier quoted context omitted.

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…

>The difference between Go and Java is that in Go a type need not declare its adherence to an interface up front. Go can't declare adherence up front, and in my view that’s a problem. Most of the time, explicitly stating your intent is best, for both humans reading the code and tools analyzing it. That said, structural typing has its moments, like when you need type-safe bridging without extra boilerplate.

One of the main uses for interfaces in Go is defining the contact for _your_ dependencies. Rather than saying your function takes a socket, if you only ever call Write(), you can take a Writer, or define another interface that is only the set of functions you need. This is far more powerful than declaring that your type implements an interface up front. It allows for things like e.g. multiple image libraries to implement your interface without knowing it, enabling your project to use them interchangeably. And as another commenter said, you can have the compiler verify your compliance with an interface with a simple (though admittedly odd looking) declaration.

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

#35
post #15

Earlier quoted context omitted.

Fabrice also wrote the Tiny C compiler, so very much his language of choice .. For those used to the language it was seen as "lighter" and easier to add OO like abstractions to your C usage than bog down in the weight and inconsistencies of (early) C++ https://bellard.org/ https://en.wikipedia.org/wiki/Fabrice_Bellard

> weight and inconsistencies of (early) C++ Since very little is ever removed from C++, all the inconsistencies in C++ are still there.

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 issues with C and C++ that it just makes sense to use. An example from a codebase I spend a lot of time in is

    int val;
    bool valueSet = getFoo(&val);
    if (valueSet) {}
    printf(“%d”, val); // oops
The bug can be avoided entirely with C++

    if (int val; getFoo(&val)) // if you control getFoo this could be a reference which makes the null check in getFoo a compile time check
    {}
    printf(“%d”, val); // this doesn’t compile.

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

#36

Earlier quoted context omitted.

interfaces in Go are structural. Interfaces in Java are nominal and require immediate declaration of intent to implement at type definition.

Shouldn’t this be named phenomenal rather than structural ? In both cases there is a structure assumed, but one is implicitly inferred while the other one is explicitly required.

I think you’re making a joke, but in Go you get both. You can have the compiler enforce that you implement an interface with a simple declaration. Most people do.

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

#37
post #27

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.

You can take it a step further: - instead of setting the same function pointers on structs over and over again, point to a shared (singleton) struct named "vtable" which keeps track of all function pointers for this "type" of structs - create a factory function that allocates memory for the struct, initializes fields ("vtable" included), let's call it a "constructor" - make sure all function signatures in the shared…

This is pretty much how you do COM[1] in C[2].

[1]: https://learn.microsoft.com/en-us/windows/win32/com/com-tech...

[2]: https://www.codeproject.com/Articles/13601/COM-in-plain-C

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

#38
post #29
post #24

Earlier quoted context omitted.

Only if your entire API doesn't contain any C++.

C is also C++, at least the C89 subset.

it actually isn't

https://www.stroustrup.com/bs_faq.html#C-is-subset

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

#39
post #27

Earlier quoted context omitted.

You can take it a step further: - instead of setting the same function pointers on structs over and over again, point to a shared (singleton) struct named "vtable" which keeps track of all function pointers for this "type" of structs - create a factory function that allocates memory for the struct, initializes fields ("vtable" included), let's call it a "constructor" - make sure all function signatures in the shared…

Is this satire? That’s almost exactly the C++ way.

Some say C++ is satire

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

#40
post #27

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.

You can take it a step further: - instead of setting the same function pointers on structs over and over again, point to a shared (singleton) struct named "vtable" which keeps track of all function pointers for this "type" of structs - create a factory function that allocates memory for the struct, initializes fields ("vtable" included), let's call it a "constructor" - make sure all function signatures in the shared…

> You can take it a step further:

No, that is essentially what Linux does in this article (and by the looks of it also ffmpeg).

struct file does not have a bunch of pointers to functions, it has a pointer to a struct file_operations, and that is set to a (usually / always?) const global struct defined by a filesystem.

As you can see, the function types of the pointers in that file_operations struct take a struct file pointer as the first argument. This is not a hard and fast rule in Linux, arguments even to such ops structures are normally added as required not just-in-case (in part because ABI stability is not a high priority). Also the name is not mangled like that because it would be silly. But otherwise that's what these are, a "real" vtable.

Surely this kind of thing came before C++ or the name vtable? The Unix V4 source code contains a pointers to functions (one in file name lookup code, even) (though not in a struct but passed as an argument). "Object oriented" languages and techniques must have first congealed out of existing practices with earlier languages, you would think.

Post reply on HN