Symbian
Symbian Developer Library

SYMBIAN OS V9.4

Feedback

[Index] [Previous] [Next]


How To Migrate Character Conversion Plugins to ECOM

The Character Conversion (CHARCONV) framework has an architecture that supports plugin DLLs for converting between Unicode and other character sets. Each conversion is performed by a plugin DLL that is loaded at run-time. In Symbian OS pre-v9.1 these plugin DLLs resided in the \system\charconv directory, from where they were loaded by CCnvCharacterSetConverter.

However, in a Secure Platform all binaries - including plugin DLLs - are data-caged and located in \sys\bin; so CCnvCharacterSetConverter cannot find and load them. Consequently, in Symbian OS 9.1 the CHARCONV plugin framework has been migrated to the more secure, generic ECOM plugin framework. Any third-party CHARCONV plugins developed for the non-secure versions of Symbian OS will not work with the secure CHARCONV, and will also need to be migrated.

This document describes how to migrate CHARCONV plugins to the ECOM plugin framework.

[Top]


ECOM basics

ECOM provides a standard mechanism for binding implementations to interfaces at run time: it supports the dynamic discovery and instantiation of objects conforming to specified interfaces.

To change a CHARCONV plugin to an ECOM plugin:

  1. Convert the plugin to an implementation of a pre-defined ECOM interface definition. This is described in the next section, Interface Definition.

  2. Mark the new interface implementation as an ECOM discoverable plugin.

Example Plugin Migration to the end of the page describes how to convert a fictitious CHARCONV plugin to an ECOM plugin.

[Top]


Interface definition

CHARCONV defines the interface class, CCharacterSetConverterPluginInterface, from which the ECOM plugins are derived. This class is defined in the file CharacterSetConverter.h:

CCharacterSetConverterPluginInterface provides the same function prototypes as defined in non secure plugin source files.

const TUid KCharacterSetConvertorInterfaceUid = {0x101F7F1D};
 
class CCharacterSetConverterPluginInterface : public CBase
    {
    public: 
        virtual const TDesC8& ReplacementForUnconvertibleUnicodeCharacters() = 0;
 
        virtual TInt ConvertFromUnicode( 
            CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, 
            const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, 
            TDes8& aForeign, 
            const TDesC16& aUnicode, 
            CCnvCharacterSetConverter::TArrayOfAscendingIndices&
            aIndicesOfUnconvertibleCharacters) = 0; 
            
        virtual TInt ConvertToUnicode( 
            CCnvCharacterSetConverter::TEndianness
            aDefaultEndiannessOfForeignCharacters, 
            TDes16& aUnicode, 
            const TDesC8& aForeign, 
            TInt& aState, 
            TInt& aNumberOfUnconvertibleCharacters, 
            TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter) = 0; 

        virtual TBool IsInThisCharacterSetL( 
            TBool& aSetToTrue, 
            TInt& aConfidenceLevel, 
            const TDesC8& aSample) = 0;
 
        static CCharacterSetConverterPluginInterface* NewL(TUid aInterfaceImplUid);
 
        virtual ~CCharacterSetConverterPluginInterface(); 
        
    private: 
        TUid iDtor_ID_Key; 
    }; 

The class defines the four functions that the plugin needs to implement.

[Top]


Example plugin migration

The fictional files TIS620.MMP and TIS620.CPP comprise a non-secure plugin DLL that supports the conversion of TIS620 (a Thai character set) to and from Unicode. Also required is SCnvConversionData - the conversion data for the foreign character set - which is generated from the conversion information for that character set.

TIS620.MMP

// TIS620.MMP 
// The plugin mmp file might not be exactly the same as below 
// but the following contains the relevant information 
             
TARGET              TIS620.CPL  
TARGETPATH          \System\charconv 
TARGETTYPE          DLL 

UID                 0x1000601a 0x1000507f 
 
Sourcepath          ..\xyz
Source              TIS620.CPP
 
SourcePath          \epoc32\Build\generatedcpp\charconv 
Source              G_TIS620.CPP
 
Systeminclude       ..\include \epoc32\include
Library             EUSER.LIB  CHARCONV.LIB
    
Start Resource     TIS620.rss //resource file containing the characterset name 
End

Deffile                \epoc32\release\wins\CONVPLUG.DEF 
                
Start                   WINS
Baseaddress         0x7b9200000
End

TIS620.CPP

// The most basic plugin code would have something like the following        
    
#include <E32STD.H>
#include <CHARCONV.H>
#include <CONVGENERATEDCPP.H>
#include <CONVPLUG.H>
 
GLDEF_C TInt E32Dll(TDllReason) 
      { 
      return KErrNone; 
     } 

EXPORT_C const TDesC8& ReplacementForUnconvertibleUnicodeCharacters()
      { 
      return SomeFunctionToReturnReplacementCharacters(); 
      } 

EXPORT_C TInt ConvertFromUnicode(
      CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, 
      const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, 
      TDes8& aForeign, 
      const TDesC16& aUnicode, 
      CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters) 
      {
     return DoSomeConversionFromUnicode(aForeign, aUnicode); 
      } 
     
EXPORT_C TInt ConvertToUnicode( 
      CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, TDes16& aUnicode,  
      const TDesC8& aForeign,  
      TInt&,  
      TInt& aNumberOfUnconvertibleCharacters,  
      TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter) 
      {
      return DoSomeConversionToUnicode(aForeign, aUnicode); 
     }

EXPORT_C TBool IsInThisCharacterSetL( 
      TBool& aSetToTrue,  
      TInt& aConfidenceLevel,  
      const TDesC8&) 
      { 
      return DoSomething();  
      }

EXPORT_C void Reserved_2()    
      {
      }

EXPORT_C void Reserved_3()
      {
      }

EXPORT_C void Reserved_4()
      {
      }

EXPORT_C void Reserved_5()
      {           
      }

EXPORT_C void Reserved_6()
     {
      }

EXPORT_C void Reserved_7()
     {
      }

EXPORT_C void Reserved_8()
     {
      }

All the plugin source files will be similar to TIS620.CPP.

The interface class, CCharacterSetConverterPluginInterface, provides the same function prototypes as defined in the non secure plugin source files. Changing an existing plugin to be an implementation of the interface is described in the next section.

[Top]


Implementing the interface

The plugin source file defines and implements a class derived from CCharacterSetConverterPluginInterface.

TIS620.CPP

#include <E32STD.H> 
#include <CHARCONV.H> 
#include <CONVGENERATEDCPP.H> 
#include <ecom/implementationproxy.h> 
#include "CharacterSetConverter.h" 

class CTIS620Implementation : public CCharacterSetConverterPluginInterface 

public: 
     virtual const TDesC8& ReplacementForUnconvertibleUnicodeCharacters(); 
     virtual TInt ConvertFromUnicode( …same list of arguments as defined in CCharacterSetConverterPluginInterface); 
     virtual TInt ConvertToUnicode(  …same list of arguments as defined in CCharacterSetConverterPluginInterface); 
     virtual TBool IsInThisCharacterSetL( …same list of arguments as defined in CCharacterSetConverterPluginInterface); 

     static CTIS620Implementation* NewL(); 
     virtual ~CTIS620Implementation(); 

private: 
     CTIS620Implementation(); 

}; 
const TDesC8& CTIS620Implementation::ReplacementForUnconvertibleUnicodeCharacters() 
     { 
     // same implementation as the pre-v9.1 plugin file
     return SomeFunctionToReturnReplacementCharacters(); 
     } 

TInt CTIS620Implementation::ConvertFromUnicode( ...) 
     { 
    // same implementation as the pre-v9.1 plugin file 
     return DoSomeConversionFromUnicode(aForeign, aUnicode);  
     }

TInt CTIS620Implementation::ConvertToUnicode( ...) 
     { 
     // same implementation as the pre-v9.1 plugin file 
     return DoSomeConversionToUnicode(aForeign, aUnicode);  
     }
 
TBool CTIS620Implementation::IsInThisCharacterSetL( ...) 
     {
     // implementation as the pre-v9.1 plugin file 
     return DoSomething();
     }

CTIS620Implementation * CTIS620Implementation::NewL() 
     {
     CTIS620Implementation * self = new (ELeave) CTIS620Implementation;
     Return self;
     }

CTIS620Implementation::CTIS620Implementation()
     {
     //default constructor.. do nothing
     }

CTIS620Implementation:: ~CTIS620Implementation()
     {
     //destructor .. do nothing
     }
     
// ADD THE FOLLOWING IN YOUR SOURCE FILE 
                
// ECOM CREATION FUNCTION 
        
const TImplementationProxy ImplementationTable[] = 
     {
     IMPLEMENTATION_PROXY_ENTRY(0x1000507f, CTIS620Implementation::NewL) 
     }; 
     
EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) 
     { 
     aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); 
     return ImplementationTable; 
     }

Note: The source file does not contain #include <Convplug.h>, because the plugin is now derived from CCharacterSetConverterPluginInterface.

The ECOM creation functions are described in the ECOM architecture specification documents.

[Top]


The project file for the CHARCONV ECOM plugin

Change the MMP file to look like this:

// TIS620.MMP 
//
TARGET              TIS620.DLL 
TARGETTYPE          PLUGIN  
CAPABILITY          All -Tcb
uid                 0x10009D8D 0x12221212
VENDORID           0x70000001

SourcePath          ..\xyz
Source              TIS620.CPP

SystemInclude       ..\include \epoc32\include

Library             EUSER.LIB CHARCONV.LIB ECOM.LIB

Start resource     TIS620.RSS
Targetpath          \resource\charconv
End

Start resource     12221212.rss
#ifdef              SYMBIAN_SECURE_ECOM
target              TIS620.RSC
#endif
end

Note: The following changes to the file:

[Top]


Creating an ECOM registry resource file

For the ECOM framework to know that a plugin is implemented for a defined interface, you must provide an ECOM resource file. This is the resource file (12221212.rss) added in the MMP file in the previous section.

12221212.rss

#include "Ecom/RegistryInfo.rh"
    
RESOURCE REGISTRY_INFO theInfo
    {
    dll_uid = 0x12221212;
    interfaces =
        {
        INTERFACE_INFO
            {
            interface_uid = 0x101F7F1D;
            implementations =
                {
                IMPLEMENTATION_INFO
                    {
                    implementation_uid = 0x1000507f;
                    version_no = 1;
                    display_name = "TIS620";
                    default_data = "TIS620 converter version1";
                    opaque_data = "";
                    }
                };
            }
        };
    }

The implementation_uid matches the third UID of the pre-v9.1 plugin DLL.

Note: In the ECOM plugin source file,TIS620.CPP, (see Interface Implementation), the line:

IMPLEMENTATION_PROXY_ENTRY(0x1000507f, CTIS620Implementation::NewL)

includes a reference to 0x1000507f, which matches the pre-v9.1 DLL UID. The macro in this line is mapping the implementation UID to the implementation creation function.

Non-secure CHARCONV dynamically loads plugins by searching for the plugin DLLs in the \system\charconv directory, and - if it finds them - using the DLL's third UID to identify the one to load.

ECOM uses the implementation_uid defined for a particular implementation in the ECOM resource file. To maintain binary compatibility when converting a plugin, and to ensure that CHARCONV loads the same plugin, change the implementation_uid to match the pre-v9.1 plugin DLL UID.

[Top]


Changing the IBY file

To add plugins to ROM while building it, you must change the plugin related lines in the IBY files from:

file=ABI_DIR\BUILD_DIR\TIS620.CPL                 System\Charconv\TIS620.CPL 
data=MULTI_LINGUIFY(RSC ZSYSTEM\Charconv\TIS620   System\Charconv\TIS620)

To:

ECOM_PLUGIN(TIS620.DLL, 12221212.rsc) 
data=MULTI_LINGUIFY(RSC ZRESOURCE\Charconv\TIS620 Resource\Charconv\TIS620)