C/C++ Portability Guide

by Warren Young

Introduction

Most Palm programs today are written in C, because C is ideally suited to programs that must be small and fast, essential attributes for a Palm program. Palm programming also involves GUI development, a particular strength of C++.

The two most important C/C++ compiler suites for the Palm platform are PRC-Tools and CodeWarrior. Both of these products are compliant with the language portion of the ISO C standard, and are both reasonably close to ISO C++ language compliance. Unfortunately, neither has a complete Standard C or C++ Library. This article will detail those limitations, and tell you where workarounds are available.

Aside: In ISO C parlance, PRC-Tools and CodeWarrior are freestanding implementations of the language, which means they're compliant, yet not a complete implementation. Most freestanding implementations are for embedded platforms, which arguably includes Palm OS.

The Standard C Library

Palm OS includes most of the Standard C Library functions, so that your program doesn't have to link in a separate C library. But, Palm changed all the function names to match the Palm OS function naming scheme. For example, a near-equivalent of the C function sprintf() exists in Palm OS, but it's called StrPrintF().

Both PRC-Tools and CodeWarrior include "shim" functions that let you use C function names to call the equivalent Palm OS functions. Sometimes these shims are just macros, in which case they don't add any size to your program over calling to the API. Other times, they are actual functions, so they do carry a small size penalty. For example, using memset() with PRC-Tools will cause the linker to bring in a 48-byte shim that calls the Palm OS function MemSet() for you.

Scott Johnson pointed out an interesting alternative to macros: define system trap functions with C names that call their Palm OS equivalent. For example, to call Palm OS's StrLen() function by the C name strlen(), you could add this declaration to your program:

                Int16 strlen(const Char *src) SYS_TRAP(sysTrapStrLen);

This method has a few advantages over macros. First, this gives you function call semantics instead of macro semantics. (If you don't know why macro semantics are a problem, go read a book on C style or a "programming traps" type book. I'd recommend C Elements of Style by Steve Oualline, but it's out of print.) A second advantage is, CodeWarrior can do code completion (argument lists and such) with the system trap, but not with a macro or shim function. The main disadvantage of this method is that it only works when the C function and the equivalent Palm OS function share the same function signature. This isn't always the case.

You don't have to do anything special with PRC-Tools to use the Standard C Library. To use it with CodeWarrior, you need to add {Compiler}/MSL to your system access path.

Problem Functions

Here's a list of the functions I know about in Palm OS where the C emulation is imperfect:

Function Problem Description
  MemSet()   Doesn't use the same parameter ordering as memset().
  StrPrintF()   Doesn't support floating-point format specifiers. (Follow the link for a solution.)
  SysQSort()   Has an extra parameter that qsort() doesn't have. This is a double problem because it passes the value you give in that parameter to the comparison function, so if you're porting C code that uses qsort() to Palm OS, you will have to redefine your comparison functions to "eat" that extra parameter.
Standard C Library Coverage

The following table shows where Palm OS mimics Standard C Library (ISO 9899:1995) functionality, and where PRC-Tools or CodeWarrior provides either a shim or its own implementation of a given set of functionality.

CW Note: CodeWarrior (probably) includes every header in the table below, but only the ones marked "full" should be used in Palm OS programs. The reason being, CodeWarrior for Palm OS includes the same Metrowerks Standard Library (MSL) that ships with all their other packages. Rather than pare the MSL down to what works on Palm OS, they ship the entire thing, much of which doesn't yet work on Palm OS. Some of the headers marked "none" do have some inline functions in them that do work on Palm OS, but I don't have a list of what these are.

PRC-Tools Note: I have made some patches to PRC-Tools' libc to bring it into closer compliance with ISO C; the table below reflects PRC-Tools with these patches applied. They were submitted to the PRC-Tools maintainers on 2001.02.17. They will remain available here until they appear in a released PRC-Tools version.

ISO C Header Close Equivalent in Palm OS PRC-Tools CodeWarrior
  assert.h   ErrFatalDisplayIf()   full   none
  ctype.h   TxtChar*()   full   none
  errno.h   none   full   none
  float.h   none   full   full
  iso646.h   none   full   full
  limits.h   none   full   full
  locale.h   International Feature Set   none   none
  math.h   none1   nonstandard2   none
  setjmp.h   none   full   none
  signal.h   none   none   none
  stdarg.h   Core/System/Unix/unix_stdarg.h   full   full
  stddef.h   OffsetOf() only   full   full
  stdio.h   Core/System/StdIOPalm.h   broken3   none
  stdlib.h   various4   partial5   none
  string.h   Str*() and Mem*()   full   full
  time.h   Tim*() and Date*()   partial   none
  wchar.h   International Feature Set   none   none
  wctype.h   partial: TxtChar*()   partial   none

  1. Palm OS itself doesn't provide equivalents for the Standard C Library's math.h functions, but there is MathLib. See the floating-point article for more info on MathLib and related things.

  2. PRC-Tools's math functions appear to use single-precision math, but the ISO C standard specifies double precision. Use MathLib if you need double precision math.

  3. PRC-Tools does include a stdio.h, but I think it was included by mistake; there is a header file, but no corresponding C file defining the declared functions. Use Palm OS's unix_stdio.h or StdIOPalm.h instead.

  4. stdlib.h is the dumping ground of the Standard C Library: it might as well have been called misc.h. Therefore, it's not possible to point to a particular part of the Palm OS API and say "this is a clone of stdlib" -- the clone functions are scattered everywhere in the Palm OS API.

  5. From PRC-Tools stdlib.h: "This header is the beginnings of an ISO C stdlib.h. Probably some of the functions declared below are not actually included in our little libc, or are not correct. This area needs work!"

The Standard C++ Library

You can separate the Standard C++ Library into two main parts: STL and "all the rest". For the latter, both CodeWarrior and PRC-Tools are pretty weak. CodeWarrior only has a working <new> header. PRC-Tools has <new>, <exception> and <typeinfo>, but it's missing the obvious companion to <exception>, <stdexcept>.

CodeWarrior 7 includes a limited version of STL. (I.e. Not completely ISO C++ compliant.) To use it, you just have to add {Compiler}/Palm OS 3.5 Support/CodeWarrior/(MSL) to your system access path.

PRC-Tools doesn't include STL. To get STL, you might try to port SGI STL, which is what ships with the GNU tools on "real computers". Alternatively, you could try my hack-and-slash port of the pre-Standard HP STL. I chose to port this version since it's quite a bit simpler than the Standard C++ STL, yet still quite useful. If you decide to download and use it, you're on your own: I don't have the time or interest to field bug reports or support requests.

The main problem with STL -- on all platforms -- is that it has a tendency to balloon program sizes. This is an annoyance on most platforms, but of critical concern on Palm OS devices due to all the system limits. Consider this test code:

                int compint(const void* p1, const void* p2, long int other)
                {
                    return *((int*)p1) - *((int*)p2);
                }

                void test()
                {
                    const int numfoos = 100;
                    int* foo = new int[numfoos];
                    for (int i = 0; i < numfoos; ++i) {
                        foo[i] = (100 - i) * 10;
                    }

                    SysQSort(foo, numfoos, sizeof(int), compint, 0);

                    delete[] foo;
                }

I dropped this into the Hello World example, and called test() from StartApplication(). I built it with PRC-Tools 2.0.90, and got an 18,750 byte PRC file. (-O2 -fno-exceptions -fno-rtti).

Now consider this equivalent STL-style code:

                void test()
                {
                    const int numfoos = 100;
                    vector<int> foo;
                    for (int i = 0; i < numfoos; ++i) {
                        foo.push_back((100 - i) * 10);
                    }

                    sort(foo.begin(), foo.end());
                }

That change makes for a 19,104 byte program, not an insignificant size jump. I suspect that the extra size is mostly in the sort() function, whereas the previous example uses the SysQSort() functinon, which is in the Palm's ROM. Consider how many other functions you will cause to be pulled into your program by using STL, and also consider that vector is the simplest STL container.

A more pressing question is, why is a simple program like this 18 KB? The culprit appears to be the C++ new operator. If I change the first program to use MemPtrNew(), malloc() or a simple array, the executable drops to under 2 KB. It might be possible to see a similar size drop in the STL version, by changing the allocator mechanism to use MemPtrNew(), but that would only work for containers holding primitive data types or structures of primitives. If you instantiate a container with a class that has a constructor, you need operator new, or the class's constructor won't get called.

Ben Combee did a similar test in CodeWarrior 7. His SysQSort()-based version made a 7,620 byte PRC file, and his STL version was 9,166 bytes. He reported that most of the size hit was in the sort() and vector template instantiations.

You may also want to read my other criticisms of using C++ for Palm programming.

Acknowledgements

Ben Combee provided several insights and other bits of data for the CodeWarrior discussion in this article. Thanks, Ben!

Copyright © 2001 by Warren Young. All rights reserved.