Skip over navigation

The Lost continent of

You've found a bug on my site!

In science it often happens that scientists say, 'You know that's a really good argument; my position is mistaken,' and then they actually change their minds and you never hear that old view from them again. They really do it. It doesn't happen as often as it should, because scientists are human and change is sometimes painful. But it happens every day. I cannot recall the last time something like that happened in politics or religion.

Carl Sagan 1987 CSICOP keynote address


There's much more to life than Windows™

Maybe I'm just an egotist, but I want my code to be used by a maximum number of users, for a maximum length of time. I want to write code that works, no matter what kind of computer you have, and I want to write code that won't be obsolete next year.

To that end, I've spent a lot of time investigating various options, libraries, even languages — and have come up with a few guidelines to share.

Cross-Platform Programming

Obviously it is useful to be able to run your program on more than one hardware platform, with more than one operating system.

The five areas in program development where we have to carefully consider portability issues are:

  1. Compiler Language Features

    Extensions to the core language provided by your system, or the idiosyncrasies of your particular compiler can cause problems. Try and use standard language features exclusively, or keep non-standard stuff in a separate class, or source file. Developing your code under more than one compiler at once is a good way to keep yourself honest on this score.

  2. Libraries

    A particular code library may be available only on a limited number of systems, or have some non-standard features. Try and use a solid cross platform library if possible. It's hard to get around this one, but sometimes an alternative can be found. If not, a valid strategy is to write a wrapper class that your application uses to call the needed library features.

    This way, you can replace the library on another platform by replacing your wrapper class, rather than having to modify all the code that uses the library's features. The idea is to always keep things that might need to change in one place — an extension of the ODR (one definition rule), and always a good design policy...

    Be sure also to use the Standard C++ Libary as much as possible. The Boost library is also worth checking out — it has some great stuff, and was begun by members of the C++ Standards Committee Library Working Group...

  3. GUIs (Graphical User Interfaces)

    I like command-line programs. You can use them interactively, or script them. You can pipe their output (or input) easily to another program, or a file. They're powerful and fun ...and they don't sell well. You almost always need a GUI to make your typical user (or manager) happy, but GUIs are usually extremely platform dependant.

    One solution is to keep the UI parts of your program seperate from the rest of the code. You then write an interface for every target platform, using the native libraries for each. One interface using Microsofts MFC, another using Mac OS X Cocoa framework, and another using GTK+ for Linux. You can use Makefiles to coditionally build and link them to the main code for each platform.

    A better solution may be to use a cross-platform GUI toolkit. Two notable cross-platform UI libraries are the Qt framework, and wxWidgets (formerly wxWindows).

    I love Qt — it has been extremely well designed, and is fun to use. It's availible either freely under the opensource GPL license (for non-commercial projects), or as a commercial library.

    wxWidgets is much more 'free' than Qt — you can use it freely in even commercial projects. Some impressive programs (eg. Audacity) have been written it it also.

  4. Machine Architectures

    At a low level, C++ provides little guarantee about the number of bits used in the various primitive data types. If you are doing any bit-fiddling in your application, it may matter to you if an int is 32, or 64 bits long. Using typedefs inside a namespace is one way of dealing with this, wrapper classes are another.

  5. I18n & L10n (Internationalisation and Localisation)

    At some point your program may need to either deal with input in various languages, or provide it's interface in other languages. Internationalisation (or i18n = 'i', 18 letters, then 'n') is process of preparing your program to deal with other human languages than english, Localisation is the actual process of providing translations.

    C++ provides locales and the w_char type to help you, but generally you will use something like GNU Readline, and your GUI toolkit's features to implement this. I recommend that you use UTF-8 as an encoding. It is a variable length Unicode code, which has the very nice property that any 7-bit ASCII text is also valid UTF-8 — your program can easily work with existing english text files.

It's all getting easier

The great news for cross-platform C++ programmers is that the 1998 ISO/ANSI C++ standard makes writing portable C++ programs much easier, now that is finally being widely supported by compiler vedors.

I often now have the pleasant experience of copying some source code for a program I wrote under Linux to my Windows test machine and being able to recompile it there, first time, no problems!