首先说下Symbian Ecom框架的核心思想,其实就是C++的虚函数和抽象类,也就是C++的多态。
一个Ecom的工程需要3个子工程(因为在Cabide中好像不可以直接创建Ecom的新工程,所以我一些例子自己尝试写了下)
<1>、 需要一个Ecom的接口类(interface工程);
<2>、 插件类的实现(plugin工程);
<3>、 调用接口类的client(界面显示工程);
在整个Ecom工程中的引导文件中,只需要添加接口工程和界面工程中的编译文件(.mmp)
eg:
PRJ_MMPFILES
../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);
}
inline EComInterface* EComInterface::NewL(const TDesC8& aOperationName)
{
//这个UID很重要,他必须和plugin 工程资源文件的interface_uid 相同,不然这个工厂函数不能调用具体的实现,这UID就是去找具体实现的依据。
const TUid KCalculateInterfaceUid = {0xE0009DC2};
TEComResolverParams resolverParams;
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);
}
这样就把接口类给实现好了(当然还可以实现一个解析器类,但是不是必须的);
<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" 这个dll_uid同样是client工程里面的UID3
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必须是这个16进制的数,这个好像是规定的。
这里还有一个文件名位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);这个指针会自动调用相应对象的接口函数。
注:
文章中颜色相同的是同一个UID,这个很重要的所以特别标注了下.
其他的就没有什么了,我就是这样做的,如果有什么问题,希望各位大侠指出
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/dymx101/archive/2010/03/18/5392135.aspx