Symbian OS Explained - Effective C++ Programming For Smartphones (2005) (779885), страница 51
Текст из файла (страница 51)
The architecture:• Identifies all the concrete implementations of a particular interface.234ECOM• Allows a client of that interface to specify dynamically which interface implementation should be used. The selection process is calledresolution. ECOM provides a default resolver but interface definitionscan provide their own specialized resolvers where required.• Instantiates an instance of the concrete class which implements thatinterface by calling the appropriate factory function.The class is implemented in an ECOM plug-in DLL and ECOM loadsit into the process in which the caller is running.
The plug-in may beloaded by a number of different clients running simultaneously in differentprocesses. ECOM uses reference counting to manage this, and unloads itwhen all its clients have released it.The ECOM architecture is used transparently by interface clientswithout the need for them to call any ECOM-specific functions. ECOMcreates an instance of an interface implementation dynamically, eitherby selecting a default implementation or by using a cue from the client asa way of identifying the particular implementation required.
The meansby which ECOM identifies and loads the correct plug-in is hidden fromthe client. Once an object of the concrete class is instantiated, the calleraccesses it transparently through the interface. The client does not need toaccess the concrete class itself, nor does it need to access ECOM directly,although it must link against the ECOM client library (ECOM.lib).ECOM itself uses a client–server architecture, which is discussed inmore detail in Chapters 11 and 12. The ECOM client class, REComSession, provides functions to list, instantiate and destroy interfaceimplementations.
A single instance of the ECOM client session exists perthread, and is accessed by interface instantiation and destruction code,which uses a set of static functions.The ECOM server manages requests to instantiate concrete instancesof an interface. By using resource file metadata provided by each ECOMplug-in, it constructs a registry of all interface implementations installedon the device. The server constantly monitors which implementations areavailable by means of filesystem scanning, which determines when plugins have been added or removed, by installation or on removable media.An interface implemented by an ECOM plug-in has two characteristicfeatures.
Firstly, it is an abstract class that defines a set of one or morepure virtual functions. This is the standard definition of an interface.However, in addition, the interface must also provide one or more factoryfunctions to allow clients to instantiate an interface implementationobject.The factory functions do not instantiate the object directly, becausean interface cannot predict which classes will implement it. Instead,the factory functions issue requests to the ECOM framework which, atruntime, instantiates the appropriate implementation class dynamically.As I described above, in order to determine which implementation toECOM ARCHITECTURE235instantiate, ECOM is given a cue, which may be a UID or some textwhich is passed to a resolver.
Alternatively, a list of all implementationsof a particular interface can be returned to the caller, which can thenspecify the one to use. I’ll illustrate both methods of instantiation in codelater in the chapter.If the only contact you intend to make with ECOM is as an ECOMinterface client, the good news is that you don’t need to read any moreof this chapter. However, you may find it useful to go to the end, whereyou’ll find some example code for a typical interface client and a briefsummary of the contents of the rest of this chapter.This chapter discusses how to define an interface and implement it inan ECOM plug-in DLL. I’ll illustrate the main points with example codethat defines an abstract base class interface, CCryptoInterface, whichcan be used to encrypt and decrypt the contents of an 8-bit descriptor.1I’ll show how ECOM can be used to select dynamically which of twopossible concrete implementations of the interface to use.
In the example,I’ve assumed that there are just two implementations of the interface,which differ because one uses a cryptography library implemented insoftware while the other uses a cryptographic hardware module, accessedby means of a device driver. Of course, numerous implementations ofthis example interface could exist, provided by separate plug-in DLLs,for various cryptography libraries ported to Symbian OS. However, forsimplicity, this example implements both concrete classes in a singleplug-in DLL.Figure 14.1 shows the relationship between the client, interface andimplementation classes and ECOM, using the classes from the examplecode for illustration.Interface clientNewL()FactoryfunctionInterface(CCryptoInterface)REComSession::CreateImplementationL()ECOM FrameworkResolvesandinstantiatesImplementation(CSoftwareCrypto)Figure 14.1Implementation(CHardwareCrypto)Relationship between client, interface and implementation classes and ECOM1I invented the fictional CCryptoInterface class, and all the sample code in thischapter, merely as an example of how to use ECOM.
Any resemblance to Symbian OScryptography libraries, living or dead, is purely coincidental.23614.2ECOMFeatures of an ECOM InterfaceLet’s start by considering the features of an ECOM interface:• As expected, the interface will define a set of pure virtual functionswhich a concrete instance will implement.• In addition, the interface must also provide one or more factoryfunctions that pass a cue to ECOM to enable it to instantiate an objectof the correct implementation (in the example below, the interfacedefinition has two static NewL() functions).• The interface must also provide a means for its clients to release it,such as a destructor to allow it to be deleted, or a method such asRelease() or Close().• An ECOM interface definition must also have a TUid data memberwhich is used internally by ECOM to identify an implementationinstance for cleanup purposes.Here is the definition of the example interface class, CCryptoInterface.
You’ll notice that the example interface class is a C classrather than an M class, which is what you may automatically haveexpected for an abstract interface definition from the discussion of thestandard Symbian OS class types in Chapter 1. The reason for this isclear on further inspection, because an ECOM interface class has featureswhich are atypical of an M class, such as the static instantiation methodand a TUid data member.class CCryptoInterface : public CBase{public:enum TAlgorithm { EDES, E3DES, EAES, ERC2, ERC4 };// Instantiation of a default object of this typeIMPORT_C static CCryptoInterface* NewL();// Instantiation using a cue to identify the implementation to useIMPORT_C static CCryptoInterface* NewL(const TDesC8& aCue);IMPORT_C virtual ∼CCryptoInterface();// List all implementations of this interfaceIMPORT_C static voidListImplementationsL(RImplInfoPtrArray& aImplInfoArray);public:// Interface functions to be implemented by a concrete instancevirtual void EncryptL(TDesC8& aPlaintext, TDesC8& aKey,TDes8& aCiphertext, CryptoInterface::TAlgorithm) = 0;FACTORY METHODS237virtual void DecryptL(TDesC8& aCiphertext, TDesC8& aKey,TDes8& aPlaintext, CryptoInterface::TAlgorithm) = 0;private:TUid iDtor_ID_Key; // Identification on cleanup};This example interface derives directly from CBase, but it is notmandatory for an ECOM interface definition to do so.
Interfaces may, forexample, equally well derive from another C class such as CActive,which, of course, itself derives from CBase. Although the interface isdefined as a C class, you’ll notice that a couple of the usual characteristics of a C class are missing. Firstly, the class has no explicitlydeclared constructor because it is an abstract base class and willnot itself be constructed.2 In addition, although the class defines astatic NewL() factory function, it does not define a ConstructL()method for second-phase construction.
This is because the NewL()factory method of CCryptoInterface does not use standard twophase construction, but instead calls ECOM to instantiate a suitableimplementation object.An ECOM interface has the following characteristics:• It is an abstract class with a set of one or more pure virtual functions.• It must provide one or more factory functions to allow clientsto instantiate an interface implementation object.• It must provide a means for its clients to release it, such as adestructor or a method such as Release() or Close().• It has a TUid data member, used internally to identify animplementation instance for cleanup purposes.14.3 Factory MethodsLet’s look at the implementation of the two static factory methods in moredetail.
The overload of NewL() that takes no parameters creates an objectof the default implementation of CCryptoInterface. In the example2The compiler generates an implicit default constructor when instances of classesderiving from CCryptoInterface are created, in order to construct the virtual functiontable for the class.238ECOMcode below, the method hard-codes a specific implementation (CSoftwareCrypto) by passing ECOM its UID.3 This method of specifying aparticular class assumes that the UID of at least one implementation classis known when the factory function for the interface is compiled.An alternative, more loosely-coupled, technique for instantiating adefault implementation uses the ECOM resolver. The resolver can bepassed a cue to enable it to instantiate, for example, the first concreteclass it discovers which implements that interface.
I’ll illustrate how to dothis later, when I discuss how to customize the ECOM resolver.EXPORT_C CCryptoInterface* CCryptoInterface::NewL(){// Hard-coded to use CSoftwareCrypto by defaultconst TUid KSWCryptoUid = { 0x10008EE5 };TAny* defaultCrypto =REComSession::CreateImplementationL(KSWCryptoUid,_FOFF(CCryptoInterface, iDtor_ID_Key));return (reinterpret_cast<CCryptoInterface*>(defaultCrypto));}REComSession::CreateImplementationL() is passed the UIDof the required implementation and the offset4 of the iDtor_ID_Keymember of the interface class.