GUI App: Porting an Engine for Use in a Symbian Application

This section describes the steps to port an engine for use in a Symbian application.

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.

The first stage in porting this program is to split the project into the engine (GUIAppEng) and the application (GUIApp).

The engine

The engine is written in C. At its core is the crc() function. This function accepts a file descriptor and returns the checksum and the file size.

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

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

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

The output file is GUIAppEng.dll, whose import library will be included by the UI.

The first UID specified (0x1000008d) is the standard UID for an interface DLL. 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 function will be exported from the engine's DLL.

For more information on DLLs, see DLLs.

Porting checksum - the GUI app

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.

The user interface provides two main menu commands; Calculate checksum (invokes a file selection dialog) and View checksums. When a file is selected and OK is pressed, the selected file name is retrieved and opened as shown in the following code:

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

This code fragment is taken from examples\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 displayed. The file is closed.

The file name and checksum are appended to an array, the contents of which may be viewed by selecting View checksums.

Linking to STDLIB - The project specification

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

Some potential issues

  • 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.

  • Include file clashes

    In C++ source files which use STDLIB routines, the Symbian platform C++ include files must 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 examples\stdlib\GUIApp\extern.h.

  • Stack usage

    Some programs produce the following error:

    unresolved external symbol __chkstk

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

  • 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 must 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 examples\stdlib\GUIApp\GUIApp.cpp.

Related concepts