Symbian Developer Library

SYMBIAN OS V6.1 EDITION FOR C++

[Index] [Glossary] [Previous] [Next]



Porting Guide


Overview

This topic describes how to port a range of traditional C applications to Symbian OS. It uses three examples: Hello, ConsoleApp and GUIApp. The first two are simple console-based examples. The third is a command-line driven program which has been converted into a standard Symbian application. It demonstrates how to link STDLIB into a C++ project. It also demonstrates some typical problems which may be encountered when porting C code to Symbian OS, including the restriction on writeable data in DLLs. These example code projects can all be found in directory epoc32ex\stdlib\.

Note that these examples may not be present on all Symbian OS v6.1 SDKs.

Some of the code for the second two examples was taken from the FreeBSD source code. For information on FreeBSD, see http://www.freebsd.org.

[Top]


Installing STDLIB on the target machine

If it is not already present on the target machine, STDLIB should be installed using the stdlib.sis installation file, supplied by the SDK in directory \epoc32\release\wins\udeb\ and \epoc32\release\wins\urel\. Installation using a .sis file has several advantages over copying files manually, including:

[Top]


Hello World— A minimal console application


Introduction

The code in this section has been taken from the Hello example.

This example demonstrates the most basic use of STDLIB. It consists of the single source code file, slhello.c whose sole function, main() calls printf().


The project specification

The Hello example's project definition file (Hello.mmp) contains the following project specification:

TTARGET        hello.exe
TARGETTYPE    exe
UID        0
SOURCEPATH    .
SOURCE        slhello.c
SYSTEMINCLUDE    \epoc32\include\libc \epoc32\include

LIBRARY        estlib.lib euser.lib
STATICLIBRARY    ecrt0.lib

The project includes the import libraries estlib.lib (the C standard library), and euser.lib (the E32 user library), whose services are used by STDLIB.

The project also links to ecrt0.lib using the STATICLIBRARY keyword. This file provides the E32Main() entrypoint for a .exe. It also provides other services including command-line parsing, and it calls main().

The SYSTEMINCLUDE path specifies \epoc32\include\libc\. This is the directory in which STDLIB's header files are installed.

For more information on the project specification for a .exe see How to build for an EXE target.


Building and running Hello World

To perform a debug build of Hello for the Emulator, run bldmake from the directory where the bld.inf file is located:

bldmake bldfiles

This creates the abld.bat batch file. Use abld to build the project:

abld build wins udeb

To start the emulator locate the directory containing the debug emulator, \epoc32\release\wins\udeb\ or type epoc at the command line. For more information on launching the emulator see How to start the emulator.

For information on building see How to use the Symbian build process.

To build Hello for the target machine, invoke bldmake and abld, specifying either arm4 udeb or arm4 urel.

To install Hello.exe on the target device you will need to create a .sis file using the Symbian Installation system; see the SIS file creator guide, Application installation guide and Installation reference.

[Top]


Console App — A simple console program


Introduction

This program converts a quantity from one unit of measurement into another, prompting the user for input. Conversion information is provided by slunits.dat.

This program is built and run in much the same way as hello.exe. The user is prompted for input, but it is important to note that STDLIB does not provide all of the functionality of a traditional console driver. STDLIB is intended to be a "behind-the-scenes" enabling technology, rather than an alternative user interface.

The code for the ComsoleApp program was taken from the FreeBSD source code (See http://www.freebsd.org ).


Porting units

The .mmp file project specification for ConsoleApp is the same as Hello's, except that it uses the additional source files units.c and getopt.c.

Run and build the program using abld and bldmake, as for the Hello example. For the Emulator slunits.dat is copied automatically by abld into the right directory, this location is \epoc32\wins\c\. For a target device ensure that slunits.dat is located in the directory specified in pathname.h, this is the root of the drive on which the program is installed.

To install ConsoleApp.exe on the target device you will need to create a .sis file using the Symbian Installation system; see the SIS file creator guide, Application installation guide and Installation reference.

To run it on the target device, tap on the ConsoleApp.exe icon.

Note that in porting this project to the Symbian platform a reduction in the size of the two arrays in the struct unittype, defined in units.c was made.

struct unittype {
    char *numerator[225]; // was [500]
    char *denominator[225]; // was [500]
    double factor;
};

This change was necessary because each thread has only 8k stack as standard. Failing to observe the limit on stack usage may cause a build to fail with the following error:

unresolved external symbol __chkstk

[Top]


GUI App — Porting an engine for use in a Symbian application


Introduction

The application uses the FreeBSD cksum utility as its engine.

The checksum example is an application with a user interface and an engine written in C. It is anticipated that many C programs which are ported to the Symbian platform will use this structure.


The original command-line program

A checksum is a number generated by adding together the value of all the data in a file. Recalculating a file's checksum and comparing the new value with a previously calculated value will reveal whether any changes have occurred to the file's contents.

The checksum generating code was taken from FreeBSD source code. The original FreeBSD program is a traditional command-line utility. It uses its command-line arguments to specify the files to be processed and writes the files' size, name and checksum to the standard output without any user intervention. A choice of algorithm is provided.

The first stage in porting this program to the Symbian platform was to split the project into two parts — the engine (GUIAppEng) and the application (GUIApp). The engine must be built first because its DLL is used by the UI. The engine and the user interface could be built as a single project, but producing a separate DLL for the engine means that different applications could use the same engine code.


The engine

The engine is written in C. At its core is the crc() function. This function takes a file descriptor and returns the checksum and the file size. The return value from this function is zero on success and greater than zero on failure.

The engine's project specification file (GUIAppEng.mmp) is as follows:

TARGET        GUIAppEng.dll
TARGETTYPE    dll
UID 0x1000008d 0x01000a02
SOURCEPATH    .
SOURCE        crc.c GUIAppeng.cpp
SYSTEMINCLUDE    \epoc32\include\libc \epoc32\include
LIBRARY        estlib.lib euser.lib

#if defined(WINS)
    deffile ..\GUIApp\GuiAppEngWINS.def
#else if defined(ARM)
    deffile ..\GUIApp\GuiAppEngARM.def
#endif
nostrictdef

The project includes header files from both \epoc32\include\ and from libc\. The output file is GUIAppEng.dll, whose import library will be included by the UI.

The first UID specified (0x1000008d) is the UID for an interface DLL. This must be specified for any project which produces a DLL and an import library, and where the DLL is intended for automatic loading at run-time. The second UID ( 0x01100a02) is unique to the GUIApp project.

Splitting the project into engine and UI means that the definition of crc() in crc.c must be marked EXPORT_C because this functions will be exported from the engine's DLL.

Because all DLLs need an entry point called E32Dll(), the GUIApp project includes a fourth source code file, GUIAppEng.cpp which consists of the single exported function:

EXPORT_C TInt E32Dll(TDllReason)

For more information on DLLs, see DLLs.


Porting checksum — the GUI app

Introduction

The implementation of checksum (GUIApp.app) limits the user to the selection of a single file at a time and uses the default algorithm crc(), defined in crc.c, to produce a 32-bit value.

Description

The user interface demonstrates a typical Symbian application whose engine is written in C and which uses STDLIB.

The application provides two main menu commands; Calculate checksum and View checksums. Calculate checksum invokes a CExampleChecksumDialog. This is similar to the standard file open dialog (CEikFileOpenDialog). When a file has been selected, and OK pressed, TDes::PtrZ() is used to get a pointer to the zero terminated string containing the selected filename. The selected file is opened, using open(), declared in epoc32\include\libc\sys\fcntl.h, passing in the pointer:

const TUint16* fn=iFileName->PtrZ();
    int fd = wopen((const wchar_t*)fn, O_RDONLY, 0);

This code fragment is taken from epoc32ex\stdlib\GUIApp.cpp.

open() returns a file descriptor which the engine's crc() function uses to identify the file. The checksum is calculated (unless an error occurred in attempting to open or read the file), and is printed in an infomessage. The file is closed using close() declared in epoc32\include\libc\sys\unistd.h.

The filename and checksum are appended to a descriptor array, the contents of which may be viewed by selecting View checksums.


Linking to STDLIB — The project specification

For information on Symbian applications, their project specification, and resource files, see How to build for a GUI App target

The application program includes several STDLIB header files. These files are located in the standard include directory \epoc32\include\libc\ which, as in previous examples, is specified in the SYSTEMINCLUDE line in the .mmp file. At link time, the program includes estlib.lib and the engine DLL's .lib file (GUIAppEng.lib). Unlike the previous examples in this topic, this application does not link to ecrt0.lib. In this application there is no main() and the Symbian platform provides its own E32Main().

The project specification (GUIApp.mmp) follows the typical pattern of a Symbian application's .mmp file, with some exceptions.


Some potential issues

This section describes some issues which may arise during the porting of code written in C to the Symbian platform.

Removing writeable static

The PETRAN stage of building may report a message similar to the following:

WARNING: Dll 'SLSUMENG[0x01000a02].DLL' has initialised data.

This warning, which is not reported when building for the Emulator, indicates that the DLL contains non-const static data. This is not allowed in ARM builds. If it is not obvious where the problem occurs, the associated .map file (epoc32\release\<target>\urel\<dllname>.map) contains information which can help to track down the source file involved. A search for from *(.bss) (to find uninitialised data) or from *(.data) (to find initialised data) in GUIAPPEng.map will reveal the file in which the problem occurs, and the names of the offending variables, although static variables will not be named.

For more information about the restriction on writeable static data, see Writeable static data in DLLs.

Include file clashes

In C++ source files which use STDLIB routines, the Symbian platform C++ include files should be included before any of the STDLIB files. Failure to do this will result in the following warning:

'NULL' : macro redefinition"

Mixing C and C++

C and C++ have different views about the names of functions. If you refer to a C function from C++, ensure that its prototype is declared as extern "C". If there are several such function declarations, it may be more convenient to enclose them within the following:

#ifdef __cplusplus
extern "C" {
#endif


#ifdef __cplusplus
}
#endif

See for example epoc32ex\stdlib\GUIApp\extern.h. For more information about issues which arise when mixing C and C++, refer to any good book on C++.

Stack usage

Some projects will produce the following error:

unresolved external symbol __chkstk

unless the amount of stack they use is reduced. Symbian threads have only 8k stack as standard.

Resource cleanup

The Symbian platform has a requirement that all resources which were allocated by an application must be cleaned up by the time the program terminates. On the Emulator, in debug builds, failure to do this will cause a panic from the __UHEAP_MARKEND macro.

Because the data allocated in the thread-local storage for STDLIB's DLL (the _reent structure) is not automatically cleaned up when the environment is destroyed, it must be cleaned up by the user of STDLIB.

The function to achieve this is CloseSTDLIB(). To use this function, file epoc32\include\libc\sys\reent.h should be included in the project. Call CloseSTDLIB() after the point at which it is known that code in STDLIB's DLL will no longer be called and its thread-local storage no longer needed.

For example, see the destructor for CExampleDocument in epoc32ex\stdlib\GUIApp\GUIApp.cpp.