And again that is why people use cross platform frameworks. One piece of source to maintain AND the cross platform framework takes care of the nasty idiosyncrasies of an OS so it's a win-win.
The only person who loses is the user, when they end up with an app that almost-but-not-quite feels like an app for their platform
This is definitely not the only way that works, but it's the way that's worked best for me in my experience. Another nice perk is that it makes it super easy to do:
- automated testing: you can test all of the features of the app (other than the GUI) using a unit test framework. The library doesn't have any GUI dependencies, so you can exercise all of the functionality in an automated way
- command-line tools: if you end up with a use case where you just want to use one or two features, it's super easy to link against the library. As an example, a client had a custom board that we wrote a GUI for and they were curious about how much a particular ADC on the board varied over time (and temperature in the room). I wrote up a 20 line CLI program that just queried the value of that sensor every 5 minutes and we left it to run for a few days. It just dumped out a csv that we loaded up in Excel later to look at. Way way way less work than building a new one-off feature into the GUI, plus we could easily repeat the test later on with new hardware revs.
Edit: a 3rd example
- I had a different client with the same kind of setup, custom board, etc. They had a desktop app, and they wanted to make a cut-down web version. All I had to do was load the library using Python ctypes (
https://docs.python.org/2/library/ctypes.html) and right away my web app had access to all of the functionality of the hardware. Put together a few HTTP endpoints, and they had a super simple web app that could do exactly what they wanted. If the code that accessed the external hardware was tied in with their GUI code, it would have been *way* harder to do that.