Membership

Login

ACCU Buttons

The EPOC C++ API

Last year I upgraded my Personal Organiser to a Psion Series 5
and was contemplating spending the money (175UKP) to get the EPOC
C++ SDK - EPOC is the operating system that runs the Series 5. To a
professional C++ (and hobbyist Java) developer this looked more
enticing than learning the alternative OPL "user friendly"
programming language.

I'm not really interested in writing applications for the Psion,
but there are occasions when I write utilities that it would be
nice to have available both on my desktop system and on the Psion.
Obviously some EPOC specific code would be required, but since I
keep platform specific code (such as user interfaces and
input/output) in separate modules from the core application I
expected this to be feasible.

The Psion is a small system so it would be unreasonable to
expect all the facilities of a desktop system. But since I had
already established that the C standard library was available I had
hopes of "porting" some of my less demanding programs.

Around the time I was considering buying the SDK Psion had
separated their software development under the name of Symbian. On
visiting the Symbian website [symbian] I
found they advertised an evaluation version of their C++ SDK. I
requested a copy but in August 1998 a dispute with STNC led to the
SDK becoming unavailable.

Time passed, the dispute with STNC continued and I found other
interests. So it was a surprise when sometime around the end of
January or early February I finally received this SDK. It then had
to sit on a shelf until I had time to look at it.

Contents of the
SDK

The evaluation SDK requires Windows95 or NT and Visual C++ 4 or
5 (the learning edition will do) which may be a disappointment to
those developers that resist all things Microsoft. There is a patch
on the Symbian web site that "cures some of the problems
experienced using Visual C++ 6".

The full SDK is built around two tool chains. One of these is
based on Visual C++ and targets a version of EPOC implemented on
top of Windows and allows debugging using Visual Studio. The second
tool chain is based on Cygnus's build tools distribution (gcc etc.)
and targets EPOC systems. Key elements of the latter are omitted
from the evaluation SDK.

In addition there are instructions for building a range of
example programs, coding guidelines, and an API reference. The API
covers all the EPOC operating system facilities - such as accessing
files, communications ports, and the GUI library.

Getting
started

The SDK installed easily - although it annoyed me by creating a
number of top level directories on the partition of my choice
rather than letting me specify a base directory under which to
install everything.

After installation I followed the instructions for building some
of the example programs to run using the "Emulator". This is a
library that implements the EPOC APIs under Windows and provides a
user interface via a window that looks like the Psion. The example
programs built and ran happily and I could debug into them using
Developer Studio. Looking at the code my first impression was
confusion - class instances were initialised using two phase
construction, many of the member functions had weird looking names
ending in a capital "L" and class names began either with "T" or
"C" prefix with no apparent pattern.

This led to a nagging suspicion that all was not as I had hoped
- two phase construction is a technique developed in the early days
of C++ to deal with the inability of the language to deal with
error conditions occurring in constructors. When exception handling
was adopted in the early '90s it fell into disuse.

I dived into the documentation seeking an explanation. Here I
discovered that the "coding guidelines" require two phase
construction, that "L" identifies a function that could "leave" and
that "T" and "C" are used to distinguish classes that have no
destructor from those that need to free memory at the end of their
lifetime. I also discovered "R" a prefix for classes that need to
free other system resources.

I deduced that "leaving" isn't like throwing an exception since
any function that calls an "L" function has to manually register
instances of any "C" or "R" classes with a "cleanup stack". This
delivers similar results to exception handling with the following
differences: the programmer can get the registration logic wrong
(the compiler shouldn't), and there is a runtime cost to all these
extra function calls (this can be avoided with compiler support).
There is definitely more code to maintain, but I don't have figures
to support my suspicion that there is also a space cost.

Hopefully, no-one would introduce the unwieldy mechanisms I'd
encountered in preference to using genuine exception handling! But
at the time I could find no direct indication that the version of
C++ was anything other than compatible with Visual C++ which does
have exception handling support. (I later discovered documentation
that states that exceptions - and other language features - are not
supported, but it is hidden in various parts of the API function
reference, not in the introductory material or white papers.)

From the
source

Having decided that the supported language probably lacked
exceptions I wondered what else was non-standard and decided to
email Symbian in the hope of clarifying matters:

Alan Griffiths:

Could you confirm a suspicion that has been growing as I read
through the SDK documentation - that the language supported by the
SDK is very different from that defined by the current ISO C++
Language Standard.

In particular I was puzzled by the lack of an explanation of
when one would use the cleanup stack mechanism in preference to
allowing exceptions to unwind the stack. Is this because the C++
exception handling mechanism is not supported? (On a related point
the examples seem to suggest that the "new" operator returns 0 in
place of throwing a std::bad_alloc
exception.)

I appreciate that compiler support for a number of language
features is distinctly patchy and that the development of EPOC32
spans a period of rapid evolution in C++. However, I am repeatedly
puzzled by the approaches taken. While I can surmise that these are
compromises enforced by the available compiler technology I can't
be sure since these issues do not appear to be addressed
anywhere.

>Martin Tasker(Symbian):

There were essentially two reasons for not adopting the C++
standard library when we started developing EPOC:

at the time (mid 95) the standard had not been agreed - though
the language standard was substantially in place - clearly that has
changed since

the standard library, in particular its use of templates and its
exception-handling culture, was considered too profligate in terms
of space and time for adoption in a small system - that has not
changed since Embedded C++ is evidence that we were not the only
people that shared this feeling. They didn't even support templates
at all! - we do, but we use them exclusively in "thin template"
idioms.

AG:

I can understand your reasons for not adopting the standard
library, my main concern however is the _language_

I think your choice is wiser than that of the EC++ group
[EC]. (Templates in themselves are not harmful
and can greatly enhance the type safety and reliability of some
code.)

>MT:

By default, we will pick up and deliver some support for
standard C++ as time goes by. Later this year, we will take newer
drops of Cygnus' GCC toolchain which will include more standard C++
support (our current supported technology dates from 1996). It
might then be possible to implement a C++ standard library on EPOC,
but we have as yet no plans to do that ourselves.

The accessibility of this information could be improved, and our
plans for technical papers in the first half of this year should
help.

Incidentally in EPOC C++, operator new() returns 0 on failure,
unless you use the override which appears as new(ELeave) - which
"leaves" with KErrNoMemory on failure. There was a debate in mid-96
about whether to make ELeave the default behaviour. Largely on the
grounds that this would confuse imported C++ programs too much, we
decided against.

AG:

Equally, having new return 0 causes portability problems - it
would be best if it threw std::bad_alloc. However, there are still many
platforms that implement the pre '95 semantics you describe.

I must confess to being disappointed that the supported language
was closer to EC++ than C++ but my main difficulty throughout was
the lack of documentation of what is and isn't supported.

Don't use any multiply derived types, apart from the limited M
classes.

Can't use exceptions - use the EPOC Leave mechanism.

Don't use any C++ library stuff, just the EPOC stuff. (This is
easier since you'd have to go out of your way to link them in).

Can't use dynamic casts (or other RTTI)

Beware that this version of gcc uses an older syntax for
specific templates.

Be careful about the IMPORT_C and EXPORT_C usage for dll
external declarations - you only get complaints when compiling for
gcc.

Be careful about DLL UIDs - ditto.

Ensure all build information is given via the .mmp file - resist
the temptation to add files directly into the VC++
Workspace/Project.

You can use <stdio.h>, but I'd advise against - that and
other C library stuff are there for backward compatibility - unless
you are trying to port a pure C program. If you mix and match then
you have to close down the library in a special way.

Otherwise as a rule stick to the style used in the examples and
the manual. This is pretty different from normal, and some people
moan like hell, but since all the apps are written in this style
you are much less likely to hit bugs. Try to avoid backsliding -
some people in the past have hit problems because they (as far as I
can make out) have tried to do C style string manipulation directly
on the contents of descriptors (used for strings and other
things).

My
conclusions

I guess I'm one of those that "moan like hell" because I don't
want to make a commitment to developing solely for EPOC. I'd rather
my programs were available on whatever computer I have to hand
(which is why Java interests me). If I were intent on developing
applications specifically for EPOC platforms then the non-standard
nature of the C++ used would be less important to me.

At the root of my concerns is a problem I first wrote [Griffiths] about in 1995 as a result of reading
the first public draft of the ISO C++ standard. I complained about
the many ways in which changes to the language invalidated the
experience, skills and code base of those working with it. A
particular issue is that the presence of exception handling
necessitates a different style of coding. (Of course, the decision
to include exceptions took place long before this - they are
described in the 1990 ARM [Ellis] as
"experimental" language features.)

Having spent the intervening four years becoming accustomed to
these features I find that I am addicted. My current code base
would not compile or work without exceptions, namespaces, or STL (I
could live without RTTI). I also find that the resulting programs
require less code and are more robust. (If they use
<iostream> they take a substantial, but fixed, hit in
executable size, but otherwise they tend to be smaller or have more
functionality.)

Regarding the programs that it would be nice to have available
on my Psion I'd be willing to do some rework to have them. However,
as it stands I would also need to redevelop the core application in
the supported dialect of C++ and for me this is not worthwhile.

"The EPOC C++
SDK" - A response from Symbian's Martin Tasker

I've had several discussions with Martin about the issues raised
by the above (which he has read in draft form) you may be
interested in the following response: - Alan

Your comments are understandable from your perspective but
consider the following:

the C++ facilities weren't there in GCC when we designed our
leave support

our system is entirely effective re its original design goals
and - re those goals alone - is more economical than native C++
exception facilities

compared to other palmtop systems, we're better: Windows CE, for
instance, kills apps and loses data in order to save memory: we
never do that, precisely because our exception handling stuff is
built in so deep

Compatibility with "standard" C++ (the quotes were justified in
1995) was not a design goal of the original system: we could see
the design goals of the C++ library and exception handling
mechanism diverging grossly from ours, and the GCC toolchain didn't
support exceptions as late as 1996. Our version of the toolchain
will add support for native exceptions - possibly before the year
is out. That will enable others to port the standard library, and
code using it, onto EPOC.

I actually look forward to more dyed-in-the-wool C++ programmers
such as ACCU members using EPOC for both academic/research purposes
and commercial development. Much of commercial work we've fostered
or known about hitherto has been by people from a
SIBO/C/UNIX/Java/Win32-type background - including our own in-house
developers - for whom EPOC poses an entirely different set of
learning and porting issues.