Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
The_Franz
Aug 8, 2003

Colonel Taint posted:

This is basically how the linux kernel is written.

e: Except the casting part. Probably not the casting part. That sounds awful. It's bad enough just trying to find your way through function pointer soup, but I can at least see why it's necessary and useful. Inheritance in C the way you describe it sounds pretty awful

this is how a lot of c software is written. for all of the "c++ is the devil" ranting some c developers do, they basically end up using the same patterns and manually implementing things c++ gives you for free

Adbot
ADBOT LOVES YOU

The_Franz
Aug 8, 2003

you could have it much worse

quote:

I work for a certain corporation which uses a certain product. This is its story. To put the quality of this product into perspective, let me say it’s been in development for about 20 years and has pretty much no users (besides my corp and some “hey - let’s make our own Linux crappy distro, which no one will ever use” fanatics) and no community. It was written by a C programmer who “doesn’t like the notion of ‘type’ in programming”. Let that be a prelude of what’s to follow. Envy those who don’t know it; pity those who use it.

The product is called Enlightenment Foundation Libraries and it’s the absolutely worst piece of poo poo software you can imagine. In many years of my programming career I’ve never seen something that bad, including every TDWTF CodeSOD (yes, I’ve seen them all). EFL is a set of libraries which pretend to be a worthy replacement for Qt or GTK. In essence, it’s a bunch of hacks you can (try to) use to make windows/widgets/etc. The first thing a programmer notes while using EFL is that almost nothing works. Upon closer inspection it becomes apparent that things can be forced to somewhat work with a bunch of hacks. Let’s get into an example – creating a window with a background.

Using Qt, one would write:
code:
auto widget = new QWidget{parent};
widget->show();
2 lines, all obvious, all working as expected. In EFL the workflow to achieving the same effect is as follows (code intentionally not supplied to save you from cerebral hemorrhage, and to show the Way of EFL):

Create a window.
Show the window.
Notice nothing gets shown and no error logs.
Spend hours googling/debugging and finally create a second object of type “bg” (background) with the window as parent and then show the window.
Notice nothing gets shown and no error logs.
Spend hours googling/debugging and finally also show the bg, despite later showing the window as a whole.
Oh, did I mention the documentation is poo poo and some bits are in a form of “hell if I know” (exact quote)? There is a docs section on the webpage, but try using the information there in practice – good luck.

One might wonder why there’s a background object as a first class citizen anyway? As with all things EFL, it’s a hack for creating backgrounds, which sometimes work. If it doesn’t work, there’s another first class citizen – a rectangle object which you can add to your view. Yup – there’s a hack for a hack.

But let’s go into some details. Remember the quote about types? EFL takes that philosophy seriously. Everything is a pointer to something called Evas_Object, which translates to void *. Those knowledgeable in the horrible language of C know it’s a pointer to anything. And so it is. Everything you create is an Evas_Object and every function takes an Evas_Object as the subject to work on. But why throw away type safety? Because gently caress you, that’s why! If you wonder how to know which functions can be called on a given Evas_Object, the answer is simple – you don’t. It’s all about experimenting, hacking and debugging. Calling an invalid function on an object can result in:

Nothing, leaving you wondering WTF.
An extremely helpful console message: “SPANK! SPANK! SPANK! Naughty programmer!”. Really, I’m not joking about that one.
Another extremely helpful message: “You bitch!”. And I’m not joking about that one either – it was discovered by a female coworker while trying to hack layouts to work. Perfect timing on EFL side here.
A crash, if you’re lucky, so you can debug the issue.
Things get much worse when something less trivial is needed. For example, to create two buttons next to each other you need (in addition to the steps above):

Create a widget of type box with the background as a parent (obviously!), which is not really a widget but a layout, but it’s also not a layout because a layout in EFL is something totally different and it’s not a widget. As usual – it’s a hack for positioning widgets next to each other.
Show the box.
Create an Evas_Object of type button with the box as its parent.
Show the button.
Create a next Evas_Object of type button with the box as its parent.
Show the button.
Marvel at your two buttons which took you 50-100 lines of code to create.
So you have a button and you would like to react to a click. There’s where ironically named smart callbacks come into play. You can register a callback for an event for your Evas_Object. Event type is passed to the register function as a string. Is there a list of event names? Nope. Search through examples and pseudo-docs and you might find some that work. So what happens if you guess wrong or make a typo? Nothing, of course. No easy debugging for you, mister!

Ok, but you finally have your event name and a smart callback of type:
code:
typedef void(* Evas_Smart_Cb)(void *data, Evas_Object *obj, void *event_info);
Let’s look at the parameters. Data? It’s the const void * you pass as an additional parameter to the register function. But wait! If you can pass a const, you can pass a string literal for example, which will then be de-const’d, so you can modify it at will. Welcome to the land of undefined behavior by design!

Ok, let’s move on. obj is you Evas_Object, that is anything you can imagine. Is it a button? Is it a text label? Is it a wooden table? If your callback is meant to be generic, have fun figuring that out. It usually is the object you registered your callback with. Usually. You can register a click callback on a button and obj will be the button. You can register a click callback on a list widget item and obj will not be the item.

And what’s with that cryptic event_info? Also – could be anything. It’s some info for some events, I guess. Unless it’s not and it’s just an aptly named list widget item in disguise. Or something else. Did I mention EFL doesn’t like types?

Another interesting design related to callbacks is key handling. You can register your callback for keydown events and get all the info in a neat structure named Evas_Event_Key_Down. What would you expect from such structure? Maybe a key code? Ha! EFL gives you something more – a key name. Instead of comparing integer code to some universal key number, you are forced to do a string comparison against system-dependent key name. To find if your key was A, compare the name to string “A”; to check for return key, compare to “[Return]”; to check for play button, compare to “XF86AudioPlay” and pray your application will never be ported to something else than a Linux with X.org. In short – you want to react to 20 key presses, make 20 string comparisons against names which are listed somewhere in you OS/window system documentation.

But that’s not all you get in that neat event structure. You also get a string representation of “A UTF8 string if this keystroke has produced a visible string to be ADDED.” So far so good. Wait a minute, there’s another field which gives “The logical key : (eg shift+1 == exclamation)”. So which one I should use to display the textual representation? As usual – play around, experiment and hope your solution works (it won’t). You also get a field named “data” which is some kind of data, I suppose. Nobody really knows, especially the docs.

An interesting topic is layouts. A layout (except for box layout which is actually a widget for some reason) is a definition of a collection of GUI elements written in some forsaken language. You create those files, put widget definitions inside them, compile with custom compiler (edje_cc) and use the resulting file. This leads to some problems, unknown to the sane world. For example, a layout is immutable. You make it, you stick with it. That immutability is pretty far reaching. If you place an image in a layout, you not only cannot move the image widget anywhere, but you also cannot do anything with the image data itself. The author recognized this can be a problem, especially when all competing libraries offer dynamic modification of widget layouts. An obvious solution would be making layouts dynamic, but it’s not the EFL way. Instead you can add a pseudo-element to the layout called SWALLOW (given the previous error messages, I suspect the author designed EFL while watching Redtube). This SWALLOW can them be substituted by a real widget. Therefore, if you want your layout to be truly dynamic, make a bunch of SWALLOWs in the layout which makes it extremely readable. The compiler is also worthy of noting. It always returns exit code 0, even when it fails. Have fun designing a build system with EFL in mind. This is especially entertaining when you have a previously compiled version of a layout – it gets silently used and you’re left with hours of debugging why is nothing changing on screen.

In typical lovecraftian C fashion, EFL disregards any notion of memory ownership. It frees some data you pour into it, and it doesn’t free other. Which is which? You’ll only know when your process crashes on double free. Or when your memory fills up. Or never.

One example of this memory mismanagement is a thing called a Genlist. It in essence is a list widget with some items. It has a special “feature” – it deletes items when they go out of view and allocates memory for them when they get into view. Make a quick swipe on such list on your mobile device and you can actually hear your RAM scream in agony.

There could be quite a few tomes written about the abhorrent malefaction that is EFL, but let me keep this post short. Or at least shorter than planned. Let me talk about the next version of EFL, which my corporation doesn’t use yet. This version might be publicly available or not. Hopefully not, because all developers died, but I don’t think mankind is that lucky. A little background:

Our beloved EFL main developer, whose name I dare not say or I go on a rampage, complained he had tons of bug reports about crashes etc. Something about passing wrong Evas_Objects to wrong functions. He decided to tackle the problem in the next version. I’ll let you guess which solution he choose:
  1. Incorporate type safety.
  2. Give some meaningful names for all typedefs, if type safety is too hard, so people would at least see what goes where.
  3. Don’t use pointers as pointers. Split the bits in them into 3 (or 4) groups, which would be cast to a numerical indexes into 3- (or 4-) dimensional hash map, which in turn results in a real pointer to function + object, and call it, if such exist. If not, don’t do anything and don’t give the programmer any feedback. Oh, and implement this in a way that makes the absolute maximum objects your process can have equal to 512. But don’t forget to not warn anyone when the limit gets exceed, but call given function on a random object which causes hash collision.
Small hint: it’s not 1 or 2. Welcome to the 21st century programming!

Some of you may know a Qt presentation, where someone built a fully functional media player with theme support in QML in real-time in front of an audience. Doing the same in EFL is measured in man-years. I’m pretty serious about that one. Small projects like these require teams of 5-10 programmers working up to a year.

And did I mention EFL is the basis of all applications on Tizen?

The_Franz fucked around with this message at 20:43 on May 2, 2017

  • Locked thread