Symbian Ecom框架的核心思想,其实就是 C++的虚函数和抽象类,也就是 C++的多态。
一个 Ecom的工程需要 3个子工程
<1>、 需要一个 Ecom的接口类 (interface工程 ), 也许还有解析器类及相应资源文件和相应代理和 mmp 文件 , 如果有解析器 , 则把解析器做成一个 dll
<2>、 插件类的实现( plugin工程) : 可以包括多个抽象接口类的实现 , 该 ”接口实现 ”类继承自接口类;同解析器一样 , 也需要 相应资源文件和相应代理和 mmp 文件 , 这是一个 dll.
<3>、 调用接口类的 client(界面显示工程) ;
在整个 Ecom工程中的引导文件中即 bld.inf文件中,需要添加接口工程 , plugin工程和界面工程中的 mmp文件 .
eg:
PRJ_MMPFILES
../ interfaceDefinition /InterfaceDefinition.mmp
../plugin/group/EcomPlugin.mmp
../client/Group/EcomTest.mmp
<1>、先来说下接口类的实现 ( interface):
接口类主要有三个成员,
( 1)、工厂函数;
( 2)、纯虚函数(接口);
(3)、 TUid的成员对象;
class EComInterface : public CBase
{
public:
//工厂的方法
static EComInterface* NewL(const TDesC8& aOperationName);
virtual ~EComInterface();
public:
//接口的方法
virtual TReal Calculate(TReal aA,TReal aB) = 0 ;
private:
// 实现的标示
TUid iDor_ID_Key;
};
实现 工厂函数 的方法是在一个内联文件中,文件名一般是“.inl”;
inline EComInterface::~EComInterface()
{
//根据 iDor_ID_Key调用 delete方法把工厂函数获得的接口释放掉
REComSession::DestroyedImplementation (iDor_ID_Key);
}
// 该 NewL 函数 , 创建默认的接口实现 , 在 REComSession::CreateImplementationL传入 了指定的 ” 接口实现 ” 的 UID 即 KCalculateInterfaceUid
inline EComInterface* EComInterface::NewL (const TDesC8& aOperationName)
{
const TUid KCalculateInterfaceUid = {0xE0009DC2};
// 对于此 NewL, 可以不要 resolverParams 参数 .
TEComResolverParams resolverParams; // TEComResolverParams 作用 ?
resolverParams.SetDataType (aOperationName);
resolverParams.SetWildcardMatch (ETrue);
// 这个 iDor_ID_Key系统会自动分配 ,用于标识 接口类创建的实现
TAny* interface = REComSession::CreateImplementationL(
KCalculateInterfaceUid, _FOFF (EComInterface, iDor_ID_Key),
resolverParams);
return reinterpret_cast <EComInterface*> (interface);
} //NewL
在系统启动时 , plug-in 工程会根据本工程的 dll_uid.rss 注册所有 ” 接口实现 ” 的信息 到 ECOM( 包括 plug-in 工程本身的 UID: dll_uid = 0xE8000079 , 接口 UID : interface_uid = 0x10009DC0 , 接口实现 UID: implementation_uid = 0x10009DC3 ), 所以 , 如果 通过直接传递 UID( 当然你需要实现一个带 UID 参数的工厂方法 .) 到接口类的工厂方法中 , 并传递到 REComSession::CreateImplementationL 中 , 就可以直接通过查找 ” 接口实现 ” 即 plug-in 工程的所有 ” 接口实现 ” 信息表 , 就可以查找到相应 ” 接口实现 ” 的 NewL 方法 , 并返回实例到 Client.
在接口的 NewL 方法中 , 你可以直接传递 ” 接口实现 ” 的 UID( 当然你需要实现一个带 UID 参数的工厂方法 .), 这样的话就不需要解析器 .
你可以传递相应的非 UID 的参数 , 这样的话就需要解析器类 , 那么在这个工厂函数的实现中 , 需要指定 ECOM 接口的 UID 和解析器的 UID.
实现解析器类时 , 你需要实现解析器类的定义 (.h) 和实现 (.cpp) 外 , 还要实现 UID.rss 和 代理文件及 mmp 文件 , 与 plugin 中实现这些文件类似 .
ECOM 接口的解析器插件的实现 , 其实是实现一个 ECOM 框架定义的解析器接口 CResolver.
带解析器的情况需要把解析器的 UID和解析关键字作为参数传到 REComSession::CreateImplementationL 中 。 ECom通过解析器 UID找到解析器,并且把 Inferface UID和解析关键字作为参数传入解析器。解析器会返回实现类的 UID给 ECom, ECom再根据这个 UID构造 plug-in的实例并把接口指针返回给应用程序。
<2>、其次说说插件工程( plugin)
这个工程中的类继承自接口类,需要实现接口类中的虚函数。
这里主要说说资源文件和代理的实现:
代理这个文件主要是实现一个函数和一个数组:
const TImplementationProxy ImplementationTable[] =
{
IMPLEMENTATION_PROXY_ENTRY(0xE0009DC5, EComImplemetationPlus::NewL),
IMPLEMENTATION_PROXY_ENTRY(0xE0009DC6, EComImplemetationMutiply::NewL)
};
EXPORT_C const TImplementationProxy *
ImplementationGroupProxy(TInt& aTableCount)
{
aTableCount = sizeof(ImplementationTable) /
sizeof(TImplementationProxy);
return ImplementationTable;
}
这里的两个 UID 0xE0009DC5和 0xE0009DC6 必须和 ”接口实现 ”工程的资源文件的 implementation_uid 相同,这样框架才能找到具体去实现哪一个插件的对象(也就是调用 EComImplemetationPlus::NewL 或者 EComImplemetationMutiply::NewL)。
这里资源文件的名字必须是 dll_uid + ".RSS"
RESOURCE REGISTRY_INFO theInfo
{
dll_uid = 0xE3CCB235;
interfaces=
{
INTERFACE_INFO
{
interface_uid = 0xE0009DC2;
implementations =
{
IMPLEMENTATION_INFO
{
implementation_uid = 0xE0009DC5;
version_no = 1;
display_name = "plus";
default_data = "sum";
opaque_data = "";
},
IMPLEMENTATION_INFO
{
implementation_uid = 0xE0009DC6;
version_no = 1;
display_name = "multiply";
default_data = "multiply";
opaque_data = "";
}
};
}
};
}
这个子工程里面的 mmp文件:
TARGET EComCalculatePlugin.dll
TARGETTYPE PLUGIN
UID 0x10009D8D 0xE3CCB235
CAPABILITY NONE
SOURCEPATH ../src
SOURCE proxy.cpp
SOURCE EComImplemetationMutiply.cpp
SOURCE EComImplemetationPlus.cpp
USERINCLUDE . ../../interface ../inc
SYSTEMINCLUDE /epoc32/include
SYSTEMINCLUDE /epoc32/include/ecom
START RESOURCE ../data/E3CCB235.RSS
TARGET EComCalculatePlugin.rsc
END
LIBRARY euser.lib ECom.lib
0x10009D8D 这个是 UID2 ,因为本工程是插件,所以 UID2必须是这个数 .
这里还有一个文件名位 main.cpp 他是 DLL插件的 main 函数:
#include <e32base.h>
GLDEF_C TInt E32DLL()
{
return (KErrNone);
}
<3> 最后就是这个工程的节目显示( client)
这工程里面就比较简单了,该怎么写就怎么写,和一般的 GUI程序时一样的。
调用工厂函数时: EComInterface* comInterface = EComInterface::NewL(aOperationName);
aOperationName 是参数,这个参数和 plugin工程 里面的资源文件中的 default_data 是一样的。
调用接口函数时: aResult = comInterface->Calculate(aA,aB);这个指针会自动调用相应对象的接口函数。