This section describes how to create a Charconv plug-in DLL.
The flowchart below shows the steps to create a Charconv plug-in DLL.

An example is used to explain the procedure for creating a Charconv plug-in DLL. This plug-in converts between the cp850 character set and Unicode.
Create a cnvtool source file using a text editor and save it as, for example d:\charconvfiles\data\cp850.txt. This file contains pairs of hexadecimal numbers. The first number in each pair is the encoding of a character in cp850and the second is the Unicode encoding of the same character.
... 0x00 0x0000 #NULL 0x01 0x0001 #START OF HEADING 0x02 0x0002 #START OF TEXT 0x03 0x0003 #END OF TEXT 0x04 0x0004 #END OF TRANSMISSION 0x05 0x0005 #ENQUIRY 0x06 0x0006 #ACKNOWLEDGE ...
For more information about the syntax of a cnvtool source file, refer to Cnvtool Source File.
Create a cnvtool control file using a text editor and save it as, for example d:\charconvfiles\data\cp850.ctl. This file specifies the conversion algorithms to convert both ways between ranges of characters, and other information.
Endianness FixedBigEndian
ReplacementForUnconvertibleUnicodeCharacters 0x1a # ASCII "substitute" character - must be a single character, and must be little-endian if the "Endianness" above is "Unspecified", otherwise in the same endianness as specified
StartForeignVariableByteData
# FirstInitialByteValueInRange LastInitialByteValueInRange NumberOfSubsequentBytes
0x00 0xff 0
EndForeignVariableByteData
StartForeignToUnicodeData
# IncludePriority SearchPriority FirstInputCharacterCodeInRange LastInputCharacterCodeInRange Algorithm Parameters
2 2 0x00 0x7f Direct {} # ASCII
1 1 0x80 0xff KeyedTable16OfIndexedTables16 {} # CP850
EndForeignToUnicodeData
StartUnicodeToForeignData
# IncludePriority SearchPriority FirstInputCharacterCodeInRange LastInputCharacterCodeInRange Algorithm SizeOfOutputCharacterCodeInBytes Parameters
2 2 0x0000 0x007f Direct 1 {} # ASCII
1 1 0x00A0 0x25A0 KeyedTable1616 1 {} # CP850
EndUnicodeToForeignData
For more information about the syntax of a cnvtool control file, refer to Cnvtool Control File.
Start a command prompt to run cnvtool on the source and control files as follows:
cd d:\Symbian\epoc32\tools
cnvtool.bat -generateSourceCode d:\charconvfiles\data\cp850.txt d:\charconvfiles\data\cp850.ctl d:\charconvfiles\data\g_cp850.cpp
This process generates a C++ source code file called g_cp850.cpp. It is referred to as the cnvtool -generated cpp file. It contains the SCnvConversionData data structure.
#include <e32std.h>
#include <CONVDATA.H>
#include <CONVGENERATEDCPP.H>
#define ARRAY_LENGTH(aArray) (sizeof(aArray)/sizeof((aArray)[0]))
_LIT8(KLit8ReplacementForUnconvertibleUnicodeCharacters, "\x1a");
GLDEF_C const TDesC8& ReplacementForUnconvertibleUnicodeCharacters_internal()
{
return KLit8ReplacementForUnconvertibleUnicodeCharacters;
}
LOCAL_D const TUint16 keyedTables16OfIndexedTables16_indexedEntries_foreignToUnicode_1[]=
{
0x00c7,
0x00fc,
...
}
LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable16OfIndexedTables16::SKeyedEntry keyedTables16OfIndexedTables16_keyedEntries_foreignToUnicode_1[]=
{
{
0x80,
0xff,
keyedTables16OfIndexedTables16_indexedEntries_foreignToUnicode_1
}
};
LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable1616::SEntry keyedTable1616_unicodeToForeign_1[]=
{
{
0x00a0,
0xff
},
...
}
LOCAL_D const SCnvConversionData::SVariableByteData::SRange foreignVariableByteDataRanges[]=
{
{
0x00,
0xff,
0,
0
}
};
....
GLDEF_D const SCnvConversionData conversionData=
{
SCnvConversionData::EFixedBigEndian,
{
ARRAY_LENGTH(foreignVariableByteDataRanges),
foreignVariableByteDataRanges
},
{
ARRAY_LENGTH(foreignToUnicodeDataRanges),
foreignToUnicodeDataRanges
},
{
ARRAY_LENGTH(unicodeToForeignDataRanges),
unicodeToForeignDataRanges
},
NULL,
NULL
};
For more information about the command syntax of cnvtool, refer to Cnvtool Command Syntax.
Create a cpp file which implements the CCharacterSetConverterPluginInterface class.
All of the functions defined in the interface must be implemented by the plug-in DLL. The implementations of ConvertFromUnicode() and ConvertToUnicode() must fulfil the following behavioural requirements:
They must return a negative error code (see CCnvCharacterSetConverter::TError), or the number of elements remaining in the input descriptor which have not been converted.
They must not return an error when the output descriptor is too short or there is a truncated sequence at the end of the input descriptor.
If the output descriptor is full, the input descriptor cannot be fully converted.
If the input descriptor ends with a truncated sequence, such as the first half of a Unicode surrogate pair, the first byte of a multi-byte foreign character set character code, or a truncated escape sequence of a modal foreign character set, it cannot be fully converted.
If the input descriptor consists purely of a truncated sequence they must return CCnvCharacterSetConverter::EErrorIllFormedInput.
For non-complex character sets, they can call CCnvCharacterSetConverter::DoConvertFromUnicode() and CCnvCharacterSetConverter::DoConvertToUnicode() functions respectively.
For complex character sets, for example JIS or Shift-JIS, the CnvUtilities class provides some utility functions.
To access the two (const) global objects implemented in the cnvtool-generated cpp file, you must include the convgeneratedcpp.h header file. The SCnvConversionData object generated can then be used to implement the ConvertFromUnicode() and ConvertToUnicode() functions.
Example implementation
#include <e32std.h>
#include <charconv.h>
#include <convgeneratedcpp.h>
#include <ecom/implementationproxy.h>
#include <charactersetconverter.h>
class CCP850ConverterImpl : public CCharacterSetConverterPluginInterface
{
public:
virtual const TDesC8& ReplacementForUnconvertibleUnicodeCharacters();
virtual TInt ConvertFromUnicode(
CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
const TDesC8& aReplacementForUnconvertibleUnicodeCharacters,
TDes8& aForeign,
const TDesC16& aUnicode,
CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters);
virtual TInt ConvertToUnicode(
CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
TDes16& aUnicode,
const TDesC8& aForeign,
TInt& aState,
TInt& aNumberOfUnconvertibleCharacters,
TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter);
virtual TBool IsInThisCharacterSetL(
TBool& aSetToTrue,
TInt& aConfidenceLevel,
const TDesC8& aSample);
static CCP850ConverterImpl* NewL();
virtual ~CCP850ConverterImpl();
private:
CCP850ConverterImpl();
};
const TDesC8& CCP850ConverterImpl::ReplacementForUnconvertibleUnicodeCharacters()
{
return ReplacementForUnconvertibleUnicodeCharacters_internal();
}
TInt CCP850ConverterImpl::ConvertFromUnicode(
CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
const TDesC8& aReplacementForUnconvertibleUnicodeCharacters,
TDes8& aForeign,
const TDesC16& aUnicode,
CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters)
{
return CCnvCharacterSetConverter::DoConvertFromUnicode(conversionData, aDefaultEndiannessOfForeignCharacters, aReplacementForUnconvertibleUnicodeCharacters, aForeign, aUnicode, aIndicesOfUnconvertibleCharacters);
}
TInt CCP850ConverterImpl::ConvertToUnicode(
CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
TDes16& aUnicode,
const TDesC8& aForeign,
TInt& /*aState*/,
TInt& aNumberOfUnconvertibleCharacters,
TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter)
{
return CCnvCharacterSetConverter::DoConvertToUnicode(conversionData, aDefaultEndiannessOfForeignCharacters, aUnicode, aForeign, aNumberOfUnconvertibleCharacters, aIndexOfFirstByteOfFirstUnconvertibleCharacter);
}
TBool CCP850ConverterImpl::IsInThisCharacterSetL(
TBool& aSetToTrue,
TInt& aConfidenceLevel,
const TDesC8& /*aSample*/)
{
aSetToTrue=ETrue;
aConfidenceLevel=0;
return EFalse;
}
CCP850ConverterImpl* CCP850ConverterImpl::NewL()
{
CCP850ConverterImpl* self = new(ELeave) CCP850ConverterImpl();
return self;
}
CCP850ConverterImpl::~CCP850ConverterImpl()
{
}
CCP850ConverterImpl::CCP850ConverterImpl()
{
}
const TImplementationProxy ImplementationTable[] =
{
IMPLEMENTATION_PROXY_ENTRY(0x102825AD, CCP850ConverterImpl::NewL)
};
EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
{
aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
return ImplementationTable;
}
Create an ECom registry resource file using a text editor.
102825ac.rss
#include "ecom/registryinfo.rh"
RESOURCE REGISTRY_INFO theInfo
{
dll_uid = 0x102825AC; // UID acquired from Symbian
interfaces =
{
INTERFACE_INFO
{
interface_uid = 0x101F7F1D; // fixed UID for Charconv plug-ins
implementations =
{
IMPLEMENTATION_INFO
{
implementation_uid = 0x102825AD; // UID acquired from Symbian
version_no = 1;
display_name = "CP850";
default_data = "CP850";
opaque_data = "";
}
};
}
};
}
Create an mmp file which is used to build the plug-in DLL.
TARGET cp850.dll TARGETTYPE PLUGIN CAPABILITY All -Tcb UID 0x10009D8D 0x102825AC VENDORID 0x70000001 SYSTEMINCLUDE /epoc32/include SOURCEPATH ../src/plugins SOURCE cp850.cpp SOURCEPATH /epoc32/build/generatedcpp/charconv SOURCE g_cp850.cpp SOURCEPATH ../resource START RESOURCE cp850.rss TARGETPATH /resource/charconv LANG sc END START RESOURCE 102825ac.rss TARGET cp850.rsc END LIBRARY euser.lib LIBRARY charconv.lib LIBRARY ecom.lib
Build the plug-in DLL and install it into the \system\charconv\ directory. The DLL is then available to be loaded when CCnvCharacterSetConverter::PrepareToConvertToOrFromL() is invoked.