Showing posts with label ECOM. Show all posts
Showing posts with label ECOM. Show all posts

Symbian中ECom的杂谈 Monday, October 12, 2009

   今天在newlc上看到《ECom plug-in – in the lights of Strategy Pattern 》勾起了我对ecom的兴趣。从单个plug-in执行角度看还真是符合strategy模式,不过要是从ECom framework角度看,也就是从整个结构的角度看,又符合fade模式。
    不过理论上的争论没有什么营养,对于ECom,这句话The main idea is that you can change/update the plugin implementation independently of the main application.才是根本。
    下面我说几个ecom非常小的issue,旦愿对大家有点营养。需要仔细看看

  1.  ECom是Echo component object model的缩写
  2. rss文件名字、rss文件中dll_uid必须和mmp文件中的uid3一致。要不就算是编译通过了,plug-in dll还是不能生成。
  3. plug-in dll运行在客户端的线程中。 这就使问题简单多了,不像windows上的com,弄出个套间(apartnment)。这里需要特别注意的是:客户端必须负责plug-in所用资源的释放。
  4. 在plug-in3是实现中不再需要开发者显式定义E32Dll函数,SDK会自己定义一个并把它导出来
  5. plug-in3开始支持扩展接口,概念和windows com中的一样。将在symbian os v5.0上可用。
  6. 从dll的角度看,plug-in dll只导出了两个函数。
  7. 定义proxy table的时候,尽量用IMPLEMENTATION_PROXY_ENTRY这样的宏,可读性和兼容性更好。
  8. plug-in可以本地化
  9. 当使用IMPORT_C static TAny* CreateImplementationL(
                                TUid aImplementationUid,
                                TInt32 aKeyOffset); 这样的函数的时候,需要注意编译器的版本。必须要os使用的编译器版本一致。

Essential ECom

TOPIC:
1. overview of ECom framework
2.  key functions of ECom framework
3. plug-in files
4. extend a exsiting interface


ECom is the abbreviation of Echo Component Object Model. The main idea is that you can change or update the implementation of an interface independent of the main application. It meets the software development principle: Program to an interface, NOT an implementation. In fact, ECom is typical a plug-in system. If you have mastered COM on Windows OS, it’s observable that ECom is different from COM. The purpose of COM is across various platforms and networks, so it has some special items, for example, IDL and apartment etc. ECom is not ‘reduced’ COM, ECom is just ECom.
Here all description is based on PLUGIN3

1.     Overview

The UML diagram below is from Symbian SDK. If you understanded the technology about plug-in, pls skip this chapter.




There are four clearly-defined roles in such a system.
1.         The client that wishes to instantiate the processing unit.
2.         The interface API that provides the known general functionality via a generalized set of processing tasks, whose details are determined at run-time.
3.         The instantiation mechanism or framework.
4.         The interface implementation that provides the correct processing.

From the point of view of client, a interface is a set of actions and these actions have a well-defined boundary i.e. a interface extracts some common features and these features are enough to fulfill the function required by client. After a interface is released, from the view of client it’s never changed. So a interface is not only a restriction on semantics but also a restriction on the binary structure. Chapter4 will explain how to extend a existing interface but not to destroy the binary structure of interface.

2.     Key functions of ECom framework

ECom framework is the core to provide the correct implementation of interface which the client required at run-time. Its key functions involve:
1.       To register interface implementations with ECom framework via scanning drivers. (The registry information is defined in a rss file)
2.       To keep the registry information of all plug-ins in the form of tree, which are used to resolve implementation
3.       To search and resolve the correct implementation of interface that client’s requiring.
4.       To load and unload plug-in
5.       To instance the correct implementation
ECom framework is a typical client-server architecture. Item 1~Item 3 above runs on server side. Other items run on client side. They interact with each other via REComSession.

3.     Plug-in files

Two files, plug-in dll and rsc file will be delivered after you create a plug-in. I illustrate both files in bellowing picture.



The rsc file is a registration detail file for plug-in dll type, which ECom framework utilizes to registry your plug-in to help client to search and resolve the correct interface implementation. RegistryInfo.rh, RegistryInfov2.rh and ResistryInfov3.rh define the detailed structures. Here’s a impartment notice that the source file name(the rss file name) must match the 3rd UID of dll file. On PLUGIN3, rsc file name need not match the 3rd UID, but it must match the dll file name.
Dll plug-in file provides one or more interface implementations and one proxy table. The proxy table looks like
const TImplementationProxy ImplementationTable[] =
            {
                           IMPLEMENTATION_PROXY_ENTRY(0x2000F5F4,                CImplementationClassOne::NewL),
                           IMPLEMENTATION_PROXY_ENTRY(0x20011F39, CImplementationClassTwo::NewL),
                           IMPLEMENTATION_PROXY_ENTRY(0x20011F42, CExampleResolver::NewL)
            };

EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
            {
            aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
            return ImplementationTable;
            }
It’s responsible to instance the correct implementation. A interface can be implemented by more than one implementation. And how to get the ‘correct’ interface implementation? When client wishes a interface implementation, it must provide some ‘cue’, which is some description information, then ECom framework will search and resolve a ‘correct’ implementation for client. It’s ‘correct’ because it’s the most suited one.

4.     Extend a existing interface

Assumed there is a interface CAudioPlay and the interface has been delivered.
class CAudioPlay:public CBase
{
public:
            CAudioPlay();
            virtual ~CAudioPlay();
public:
            virtual void Play() = 0;
            virtual void Stop() = 0;
};
Now a new requirement comes, a new function, void FastForword() need be inserted. If you add it into the existing interface, the integrality of binary structure of interface will be destroyed. When a client which called the function FastFowrod meets the older plug-in, which does not define this function, the client will crash. So it’s the best way to define another interface to extend the existing interface.
On PLUGIN3, there’s a extended interface mechanism. The bellowing session is from RegistryInfov3.rh.
STRUCT IMPLEMENTATION_INFO
            {
            ...
            LONG                                   extended_interfaces[];
           
            }
There are the UIDs of extended interface in the array, extended_interfaces. You can define maximum 8 extended interfaces.
For this example, you can do as bellowing. Here a extended interface is defined.
extended_interfaces = { 0x20009E4F };
Now we define the extended interface.
class MAudioPlayExtend
{
public:
            virtual void FastForword() = 0;
};
The implementation class looks like
class CImplementationClassOne: public CAudioPlay, public MAudioPlayExtend
{
...
// from CAudioPlay
public:
            virtual void Play();
            virtual void Stop();
// from MAudioPlayExtend
public:
            virtual void FastForword();
...
// to support extended interface
public:
            static TAny* GetExtendedInterfaceL(TAny* aObject,const TUid& aExtendedInterface,TUint32& aBitFlags,TAny*& releaseObject);
            static void ReleaseExtendedInterface(TAny* aObject,const TUid& aInterface);
}
The proxy table will be modified to support the extended interface as bellowing. Pay attention on the bold line.
const TImplementationProxy ImplementationTable[] =
            {
                           IMPLEMENTATION_PROXY_ENTRY3(0x2000F5F4,            CImplementationClassOne::NewL, CImplementationClassOne::GetExtendedInterfaceL,CImplementationClassOne::ReleaseExtendedInterface),
                           IMPLEMENTATION_PROXY_ENTRY(0x20011F39, CImplementationClassTwo::NewL),
                           IMPLEMENTATION_PROXY_ENTRY(0x20011F42, CExampleResolver::NewL)
            };

EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
            {
            aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
            return ImplementationTable;
            }