An Introduction to C and GUI Programming
raspberrypi.org
raspberrypi.org
The programmer just copies and pastes from the demos, makes small modifications, and it just works.
(No offense intended towards your framework, I've used gtk, qt, and swing and have never understood them like I understand nuklear and dearimgui)
It teaches you fundamentals, especially on an embedded system such as R-Pi.
The first language I learned was C on an ARM processor. Learning about registers, bit manipulation, seeing how compiler optimizes the code based on GCC flags, understanding pointers, memory management, the whole thing is difficult for a beginner but to me, it was immensely helpful. I also love Python/Julia/Java/JavaScript but man it makes you appreciate neat things higher languages offer.
One day I want to build my own 8-bit computer from discrete gates. I’m sure it won’t be a waste of time.
This is definitely not a waste of time. But though building a physical ALU from TTL is feasible, constructing a reasonable amount of memory would be a waste of time and money.
Once you have written the nand2tetris HDL for the hardware, you could translate it to Verilog and burn an FPGA quite easily.
For learning C and starting to poke at low-level embedded stuff I would recommend starting with Arduino (and then into plain AVR) - and not go anywhere near a GUI toolkit.
There is a reason we don't actually throw kids into the deep end when teaching them to swim. Most of them would just drown...
But a new GTK2 book sounds like teaching Python 2 for beginners.
GTK 2 and GTK 3
One thing worth mentioning at this point is that there are two versions of GTK in use. The current version is GTK 3, and this is still under active development – it changes quite a bit between releases.
For this reason, many people prefer to use the older version, GTK 2. This offers most of the same functionality, but it is stable code which doesn’t change very much any more. Some say that it is always better to use the latest and greatest version of anything, but more cautious old engineers (like your author…) tend to prefer the older version that has had a lot more testing and with which people have stopped fiddling about! In terms of the examples we are looking at here, there aren’t that many significant differences between the two, but just to be clear, the examples in this book will use GTK 2.
10 years being the mainline version, and having a supported compatible version for 16 years is pretty darn impressive! If GTK4.0.0 comes out next year, then GTK3 will have had 8 years being the mainline version. Its not quite win32 levels of stability, but it is not like they break this stuff every year or something...
At this point it doesn't matter that it was released 17 years ago, what matters is that there are programs using it.
Honestly, i can see Gtk1 to Gtk2 breaking compatibility since they probably did some blunders and all and it wasn't very long lived anyway, but Gtk2 to Gtk3 should have kept backwards compatibility - GUI libraries are important foundation for a platform and breaking changes breaks every application that relies on them. Instead what the developers did was not only break Gtk3 but not even try to design an API with Gtk3 that would allow Gtk4 to be backwards compatible.
It is frustrating if as a developer you want to ensure your program keeps working in the future and have the foundation it relies on sabotage you. I can release a Win32 application today and i'm certain that if people are still using x86 Windows desktops, it will work in 20 years. Hell, chances are it'll still work in Linux thanks to Wine - whereas the only way i'd get the same sort of compatibility with a "native" UI library would be to write my own toolkit and use X11 directly (and even that assuming Wayland developers wont have convinced everyone to drop X11).
Sometimes i'm just considering to just target Win32 for my stuff and tell people use Wine for Linux and macOS, it'll be more likely to work in the future than any native UI library.
Outside of games, for software that touches the Internet you probably also want libraries to get shared security updates.
And of course having to bundle 50+MB of libraries and data (themes, etc needed by a GUI toolkit and any other data by other libraries) for a small executable is a ridiculous idea by itself.
No, a desktop system should provide some minimum functionality that desktop applications can rely on and keep that functionality stable so that application can keep on working.
Systems like Flatpak have a framework system where it is possible to have a shared runtime of dependencies that multiple applications can use. A GTK1 runtime could exist (or maybe does?), for example.
Or perhaps more fitting to modern Linux desktop, Gtk1 and Gtk2 will not support Wayland nor any new functionality introduced for scaling (did you know that, despite common narrative from Wayland fanboys, X11 already provides the necessary functionality to implement per-monitor and even per-window scaling with pretty much 99% of the same code that a toolkit would need for Windows 8+ scaling, that is most likely already written? It only needs some cooperation from the window manager and this sort of code could even be implemented for XWayland.... but it needs a bit of modification from the toolkit's side too and while it could be done for Qt5 and perhaps Gtk3, it'd need Gtk2 and especially Gtk1 to be worked on, which wont happen - on the other hand, if Gtk2/3/4 were backwards compatible, all programs would benefit from such new functionality).
Also, in this universe Win32 API was released in 90s, not 80s.
Yeah, well, kinda... technically you are correct but Win32 is 99.998% backwards compatible (as an API, not ABI) with Win16 which was first released in the 80s.
Actually, IMO if you are using closures for events that are more than 5 or so statements (i'd say lines but people love to pack their lines with multiple statements), you are doing a disservice for every poor soul who will have to understand your code later.
As far as being turing complete, CSS is supposedly that, also, so good luck with that.
Here's a guy who developed a closure "library" for C: https://nullprogram.com/blog/2017/01/08/
It's clever, but he actually had to resort to assembly...
But I never found a decent beginner friendly resources.
Anyone reading this comment, please chime in with your suggestions.
https://github.com/bztsrc/raspi3-tutorial
It's also fairly popular for emulators, since it's types are orthogonal and it's low level design is well suited to designing a pseudo-machine. It's definitely being displaced in that realm by C++/Rust/Nim/etc though.
If you can figure out pointers and how to actually get the size of things (sizeof(*char) doesn't get you the size of what it is pointing at... it gets you the size of a pointer which varies depending on the architecture. sizeof(myArray) doesn't give you the number of elements in an array, it gives you the number of bytes your array can hold, to get the number of elements you must do sizeof(myarray)/sizeof(myarray[0]). sizeof() is a compile-time operator, it knows nothing of runtime) you will be pretty much 99% of the way there.
I.e. why is it that C and assembler is “fundamental”, but electronics is not?
(I have written about this before: https://news.ycombinator.com/item?id=19106922#19113359 )
For fast, efficient software there will always be low level languages such as C, C++, etc. and I would always urge more people to learn them, even if just to learn to appreciate how much is managed by their high level language and understand the trade-offs they're making with those languages.
It's called "economics". C and C++ are simply too cumbersome for most applications; most applications don't benefit from that speed (either because the deadlines aren't that critical or because the bottleneck is I/O) and their project deadlines can't afford the velocity tax they impose. Especially when many of those languages allow you to opt out of "slow" features (or FFI into C/C++/etc) for your hot path. Lastly, higher-level languages are improving: Go is probably the easiest language out there and it's almost as fast as C (in the same ballpark, but still slower) and Rust is far, far friendlier than C or C++ but it performs on par.
Don't pessimistically de-optimize either. It's harder to remove bottlenecks from mature applications than it is to plan ahead for the target platform and common use cases.
By all means, prototype in Python but if your target platform is, at minimum, a R-Pi 2 and you want the experience to be snappy even when their is high IO or CPU work being done... then don't release on Python; use the prototype to drive the implementation in C.
Maybe consider even compiling from a higher-level language into a C library to minimize the boiler-plate.
Planning goes a long way, even if you don't plan everything up front.
I disagree. It's easier to release first and change what you need later, since there might only be 1-10 sections of code that need to be changed. Python is extremely fast to write, maybe 3x faster than C. This means you can get seed funding and sales faster, and if the idea is good enough to get a decent salary, you can just hire out optimization for a v2 release. It also allows your application to appear to get better over time, which makes long-term customers happy.
Knowing your target platform and your end goals can aid in planning. Planning your architecture ahead of time can save you from having to optimize later... and often optimizing later is harder than simply doing the easy, right thing first.
> For fast, efficient software there will always be low level languages such as C, C++, etc.
this sounds like every "low level developer" ever, in that the opinions are completely removed from reality. it isn't 19<whatever>. if by inefficient, you mean slow, then java isn't anywhere near comparable to javascript or python. beyond being a completely different type of language, java is fast. so is c# and f#. so is chez scheme and sml. so are plenty of much higher-level languages than c and safer languages than c++ that are just as fast (if not faster in some cases dependent upon development time and application and developer) than c and c++.
also, c++ is low-level? it is an insanely complex high-level language.
Who cares what year it is. Fact is, with low level languages, you can write software which consumes less resources. This won't ever change.
> if by inefficient, you mean slow, then java isn't anywhere near comparable to javascript or python.
Sure, I (and presumably the poster you responded to) agree. Java is plenty fast for most things. But its memory usage is horrendous. Like seriously bad. It seems Intellij takes a solid 1.5gb to simply exist. I'd like to use Java (well, JVM based languages really) more, but basically all JVMs are memory hogs that take too long to start up. Graal might help here, we shall see.
C#, F#, Chez, et al. follow a similar suit. (Chez is probably the best of that lot, though. Would be my choice).
and you'll be much more susceptible to bugs and schedule elongation and robustness issues. that won't ever change either.
I've never dealt with Raspberry Pi world, but I can see the value of stripping the software world on one to the bare minimum. I wonder if someone has put together a FreeRTOS tool chain for it.
His reasoning is that GTK2 is stable and GTK3 changes with each iteration.
These toolkits are inevitably on their way out. The future is the browser stack, loathe though I am to accept it.
As a tangent, it wouldn't be horrible if something like a browser was used as a window manager and UI runtime a la ChromeOS except with apps running in containers (and no bastardized Linux kernel and the restrictions that come with). This would have lots of benefits--the whole frontend benefits from all of the investment going into the web (including wasm) and the whole backend benefits from the investment in containers. Notably, packaging / dependency management, process management, log management, etc would all be much simpler/easier.
[0] https://www.pcjs.org/pubs/pc/reference/microsoft/mspl13/c/c4...
There's an almost symbiotic relationship going on where the foundation doesn't exactly ignore the hobbyist or industrial communities - far from it - but they are still holding to their core mission, and these notable, but ultimately ancillary communities provide the budget for it.