Porting in c standard library

Porting Guide


Overview

This topic describes how to port some 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 also describes 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 be found in directory examples/stdlib/.

Note that these examples may not be present on all Symbian OS 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/.


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:

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

Notes

  • The import library estlib.lib is the C standard library.

  • The project also links to ecrt0.lib. 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/, which is the location for STDLIB's header files.

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


Building Hello World

To build 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, for instance:

abld build wins udeb

For information on building see How to use the Symbian build process. To run it, invoke hello.exe.

To build Hello for the target machine, invoke bldmake and abld, specifying the appropriate target platform.

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


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 in a data file, slunits.dat.

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 ConsoleApp program was taken from the FreeBSD source code (See http://www.freebsd.org/ ).


Porting the code

Build the program using bldmake and abld as the Hello example. For the Emulator, slunits.dat is copied automatically by abld into the right directory. For a target phone 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 phone you will need to create a .sis file using the Symbian Installation system; see SIS file creator guide, Application installation guide and Installation reference.

To run it on the target phone, invoke ConsoleApp.exe.


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.

The first stage in porting this program was 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 takes 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
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 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.

Because all DLLs in Symbian OS 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 provides two main menu commands; Calculate checksum (invokes a file selection dialog) and View checksums. When a file has been selected, and OK pressed, the selected filename is retrieved and opened:

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 filename 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 Symbian OS provides its own E32Main().

For information on Symbian applications, their project specification, and resource files, see How to build GUI applications.


Some potential issues

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

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 OS 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 examples/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 by default.

Resource cleanup

Symbian OS 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 examples/stdlib/GUIApp/GUIApp.cpp.

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章