|Octopull/C++: The EPOC C++ SDK|
Last year I upgraded my Personal Organiser to a Psion Series 5 and was contemplating spending the money to get the EPOC C++ SDK (EPOC is the operating system that runs the Psion). To a professional C++ (and hobbyist Java) developer this looked more enticing than learning the alternative OPL "user friendly" programming language.
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. There was reason to believe it possible since I try to keep the user interface and input/output separated from a "platform independent" core application.
Around the time I was considering this Psion had separated their software development under the name of Symbian. On visiting the Symbian website I found they advertised an evaluation version of their C++ SDK. I requested a copy but in August 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 for a while until I had time to look at it.
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.
The full SDK is built around two tool chains running under Windows. 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 (based on Cygnus's build tools distribution -gcc etc.) targets the Psion (and other EPOC systems) but is 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.
The SDK installed easily - although it annoyed me creating a number of top level directories on whichever partition I chose rather than letting me specify a base directory under which it installs 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 (there are problems with it but this is not the place to discuss them). As I discovered later, there is in fact 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.
Having reached this stage I decided to email Symbian with 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.
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. (Templates in themselves are not harmful and can greatly enhance the type safety and reliability of some code.)
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.
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've been writing exception aware code since early '95 and found that (after the initial "how can I write anything" reaction) it greatly simplifies code (and consequently saves more space that exceptions cost).
Moving to an environment without exceptions now seems like a trip to the stone age. (And would cause serious portability concerns.)
I must confess to being a little 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.
I have to thank John Forrest <firstname.lastname@example.org> for posting the following summary on usenet <nntp://comp.sys.psion.programmer> (I've corrected a few typos).
- Don't use any file scope or local static variables.
- 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).
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 the Psion (and/or other EPOC platforms) then I'd be more concerned to establish what was and what wasn't part of the supported environment. As I've indicated above this isn't easy with the evaluation SDK, but with the full SDK to try things out it would no doubt be easier.
In fairness, the EPOC dialect of C++ it is in advance of the C++ I first learnt - it has multiple inheritance and the basics of template support. And thinking back many years I remember using it quite successfully. Nonetheless the differences between EPOC C++ and ISO C++ are quite fundamental - developing a non-trivial program that is correct in both would be impractical.
I've encounter these differences before - as a result of studying the first public draft of the ISO C++ standard in 1995 I wrote an article for Overload. In this I complained about the many ways in which changes to the language invalidated the experience and skills of those working with it. A particular issue that I identified was that the presence of exception handling necessitated a different style of coding.
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 (changing the UI code, removing <iostream>, etc.). 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.
Read Martin's response to the above
 Embedded C++ is an ARM like dialect of C++ being promoted by a Japanese consortium - details may be found at http://www.dinkumware.com/
 "No such thing as a free lunch" Alan Griffiths Overload 7 ISSN 1354-3172 ( included here)
Your comments are understandable from your perspective but consider the following:
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.