Symbian
Symbian Developer Library

SYMBIAN OS V9.4

Feedback

[Index] [Previous] [Next]


How to port guide: apps to exes

This document provides step-by-step instructions on how to convert an existing DLL-type application to a new style EXE-type application. The conversion of embeddable applications requires more work than non-embeddable, so the two types are described separately.

[Top]


Non-embeddable applications

The TARGETTYPE in the MMP file changes from app to exe. However, for applications that need to also run on the EKA1 emulator, the TARGETTYPE must be exedll. Hence, the following lines should replace the existing TARGET and TARGETTYPE lines:

#if !defined(EKA2) && defined(WINS) 
TARGET ExeAppTest.app 
TARGETTYPE exedll 
deffile \epoc32\release\wins\exedllapp.def 
#else 
TARGET ExeAppTest.exe 
TARGETTYPE exe 
#endif

The TARGET filename's extension should be .exe. It is also important is that the second UID (the application identifier) remains the same: 0x100039CE. For EKA1 emulator builds, the binary produced is a DLL with the entry point exported at ordinal one. Therefore, as in the example above, a deffile statement is used to define the export.

The stack size should be explicitly set to a value greater than the default of 8K. Previously, applications were launched in a process initiated by apprun.exe which had a stack size of 20K. Therefore, to ensure the converted application will not have any problems with stack size, this is the minimum value the stack size should be set to. This is done in the MMP file with the line:

epocstacksize 0x5000

Note that embedding an EXE-app inside another EXE-app (see the Embeddable applications section below) is enough to overflow the default 8K stack.

The API for starting the application framework is in eikcore.dll, so eikcore.lib needs to be listed in the LIBRARY section of the MMP file.

The EikStart::RunApplication() function needs to be called from the EXE's entry point, passing as an argument a pointer-to-function which creates an instance of the CApaApplication-derived class (this is the same function that is exported at ordinal 1 for DLL-apps). In EKA1 emulator builds, the command line also needs to be passed to this function. This is demonstrated by the following code, which works for all builds:

#include <eikstart.h> 
LOCAL_C CApaApplication* NewApplication()
    {
    return new CExampleApplication;
    } 
GLDEF_C TInt E32Main()
    {
    return EikStart::RunApplication(NewApplication);
    }

#if defined(__WINS__) && !defined(EKA2) 
GLDEF_C TInt E32Dll(TDllReason)
    {
    return KErrNone;
    } 
EXPORT_C TInt WinsMain(TDesC* aCmdLine)
    {
    return EikStart::RunApplication(NewApplication, aCmdLine);
    } 
#endif

If the application needs to store configuration or application data, a private directory will need to be created. For more information on private directories, see the documentation on the RFs class.

The relevant functions in the RFs class for private directories are are:

RFs::PrivatePath

gets the private path for a process

RFs::CreatePrivatePath

creates the private directory for a process on the specified drive

RFs::SetSessionToPrivate

sets the session path to point to the private directory on the specified drive

[Top]


Embeddable applications

Embeddable applications are implemented as ECom plug-ins. The CApaApplication class defines the interface, and the majority of an application's code will be in the ECom plug-in. To allow an embeddable application to run as a standalone application a small EXE also needs to be created which calls the EikStart::RunApplication() function, but this time specifying the UID of the ECom plug-in rather than a pointer to the factory function.

This section describes the steps for converting an existing embeddable application to an ECom plug-in and executable.


Creating the ECom plug-in

The MMP file of the embeddable application needs to be changed to create an ECom plug-in instead of a DLL application, using the following lines:

TARGET Example_embedded.dll 
TARGETTYPE PLUGIN 
UID 0x10009d8d 0x01010101

where 0x01010101 is a newly allocated UID, not the application's original UID - this is used elsewhere, see below.

The MMP file also needs to create the ECom plug-in resource, and the original resource line needs to be modified so the application resource file(s) are created in the correct directory.

START RESOURCE 01010101.rss 
#ifdef SYMBIAN_SECURE_ECOM 
TARGET Example_embedded.rsc 
#endif 
END 

START RESOURCE Example.rss 
HEADER 
TARGETPATH \resource\apps 
LANG SC
END

The 01010101.rss ECom plug-in resource file uses the standard format for ECom plug-ins, where the interface definition UID for CApaApplications is:

const TUid KUidFileEmbeddedApplicationInterfaceUid={0x101f8c96};

The implementation UID should be the application's original UID (0x01234567 in the example below), and therefore the file should look like this:

#include <RegistryInfo.rh> 
RESOURCE REGISTRY_INFO
    {
    dll_uid = 0x01010101; 
    interfaces =
        {
        INTERFACE_INFO
            {
            interface_uid=0x101f8c96;
            implementations=
                {
                IMPLEMENTATION_INFO
                    {
                    implementation_uid=0x01234567;
                    version_no=1;
                    }
                };
            }
        };
    }

ECom.lib should be included in the library section in the MMP file.

The AIF section is not needed as the application information is now provided by the registration file, localisable resource file and icon file. A registration file should be provided to inform the framework about the embeddable capability of the plug-in. This can be achieved by setting the ‘embeddability' flag in APP_REGISTRATION_INFO structure. If a stub EXE is provided to start the ECom plug-in, set the embeddability flag to KAppEmbeddable, otherwise set KAppEmbeddableOnly. For more information about the registration file please refer to the How to port guide - data caged applications document.

The code for the application should no longer export the NewApplication() function at ordinal 1, but instead the function which informs the ECom framework of the implementations this ECom plug-in provides (as is standard for an ECom plug-in). This is demonstrated by the following code:

#include "ExampleApp.h" 
#include <ecom.h> 
#include <implementationproxy.h> 
GLDEF_C TInt E32Dll(TDllReason)
    {
    return KErrNone;
    }

LOCAL_C CApaApplication* NewApplication()
    {
    return new CExampleApplication;
    }

LOCAL_D const TImplementationProxy ImplementationTable[]= 
    { 
    IMPLEMENTATION_PROXY_ENTRY(0x01234567, NewApplication)
    };
EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) 
    { 
    aTableCount=sizeof(ImplementationTable)/sizeof(ImplementationTable[0]);
    return ImplementationTable; 
    }

Creating the standalone EXE for the application

The MMP file for the standalone EXE should create an EXE-app (as described in the Embeddable applications section above) and the EXE should have the application's UID as its third UID. The AIF file should be replaced by a registration file. The registration file is used to inform the framework that the application is capable of being embedded by setting KAppEmbeddable in the ‘embeddability' field of the APP_REGISTRATION_INFO structure.

#if !defined(EKA2) && defined(WINS)
TARGET Example.app 
TARGETTYPE exedll 
deffile \epoc32\release\wins\exedllapp.def 
#else 
TARGET Example.exe 
TARGETTYPE exe 
#endif 
UID 0x100039CE 0x01234567 
TARGETPATH \sys\bin 
EPOCSTACKSIZE 0x5000 
SOURCEPATH . 
SOURCE Example_Standalone.cpp 
USERINCLUDE . 
SYSTEMINCLUDE \epoc32\include

// Application exe registration resource file 
start resource    Example_reg.rss 
targetpath     \private\10003a3f\apps 
lang        sc 
end

LIBRARY euser.lib apparc.lib eikcore.lib

The executable need only be a 'stub' to start the application architecture with the ECom UID. Therefore the single source file should contain code similar to the following:

#include <e32std.h> 
#include <eikstart.h>

const TUid KExampleUid = {0x01234567}; 
GLDEF_C TInt E32Main()
    {
    return EikStart::RunApplication(KExampleUid);
    } 
#if defined(__WINS__) && !defined(EKA2) 
GLDEF_C TInt E32Dll(TDllReason)
    {
    return KErrNone;
    } 
EXPORT_C TInt WinsMain(TDesC* aCmdLine)
    {
    return EikStart::RunApplication(KExampleUid, aCmdLine);
    } 
#endif

Finally, the bld.inf for the application needs to be modified to build both MMP files, for example:

PRJ_MMPFILES 
Example_embedded.MMP 
Example_standalone.MMP

Embedding a new-style application in an existing application

To add a new document to an application, an overload of CApaProcess::AddNewDocumentL() has been created which can accept an ECom UID or an ECom CImplementationInformation reference. However, the existing overload of AddNewDocumentL() handles the case where the application for the document is an EXE, and attempts to find an ECom plug-in with the correct UID to create the embedded application. Therefore, existing applications (which perhaps offer a list of available embeddable applications to the user) do not need to be modified. Also, the internalising and externalising of embedded documents (via CApaDoor, etc.) works with no modifications necessary.