Using
Extended Interfaces
Framework developers define and publish extension interfaces to
the existing interfaces used in the framework. Once an interface extension
is published by the framework developer, plug-in developers implement the
extension if required.
Identify the published instantiation and extended interface UIDs and
header files of the framework.
Create a new
project file (.mmp) with targettype variable
set as PLUGIN3. Allocate UIDs for the the plug-in implementations and plug-in
DLL (UID3) as shown in the code snippet below.
TARGET cimplementationclass.dll
TARGETTYPE PLUGIN3
CAPABILITY All -TCB
// PLUGIN3 recognition UID followed by the UID for this dll
UID 0x10009D93 0x10009E37
VENDORID 0x70000001
SOURCEPATH ../src
SOURCE cimplementationclass.cpp
USERINCLUDE ../src
SYSTEMINCLUDE /epoc32/include
START RESOURCE cimplementationclass.rss
TARGET cimplementationclass.rsc
END
LIBRARY euser.lib
LIBRARY ecom.lib
Create a new resource file (.rss) of format
version 3.
CImplementationClass.rss
#include <ecom/registryinfov3.rh>
RESOURCE REGISTRY_INFO theInfo
{
resource_format_version = RESOURCE_FORMAT_VERSION_3;
dll_uid = 0x10009E37;
interfaces =
{
INTERFACE_INFO
{
instantiation_interface_uid = 0x10009DBB;
implementations =
{
IMPLEMENTATION_INFO
{
info_format = IMPLEMENTATION_INFO_RECORD_TYPE1;
implementation_uid = 0x10009E38;
version_no = 1;
display_name = "Extended Interface Example";
default_data = {"Extended Interface Example||up to 255 chars", "Max. two strings allowed"};
opaque_data = {"up to 255 chars", “max. 2 strings allowed”};
extended_interfaces = {0x10009E44, 0x10009E45};
flags = FLAG_ROM_ONLY;
}
};
}
};
}
Implement the interfaces in the plug-in implementation source files.
Implementing an interface extension in a plug-in implementation can
be done in either of the two ways:
Inheritance: The instantiation interface object is also of the type
of the extended interface object. When a user wants to instantiate the extended
interface object, the implementation simply returns a re-cast of the instantiation
interface object.
The example below shows implementing an interface extension using inheritance.
//Implementing an interface extension using multiple inheritance
class CImplementationClass : public CExampleInterface, public MExampleInterfaceExtended
{
public:
static CImplementationClass* NewL();
static TAny* GetExtendedInterfaceL(TAny* aInstantiationInterface,const TUid& aExtendedInterfaceUid,TUint32& aBitFlags,TAny*& aReleaseObject);
static void ReleaseExtendedInterface(TAny* aExtendedInterface, const TUid& aExtendedInterfaceUid);
~ CImplementationClass() {}
virtual void DoMethodL(); // from original interface
virtual void DoMethodExtended(); //from MExampleInterfaceExtended
private:
CImplementationClass() {}
};
Realizing the extended interface as separate class and objects. When
users fetch the extended interface object, the implementation allocates a
new object.
The example below shows implementing an interface extension using realisation.
// Implementing an interface extension using realization
class CImplementationClassExtended : public CBase, public MExampleInterfaceExtended2
{
public:
static CImplementationClassExtended* NewL();
~ CImplementationClassExtended() {}
virtual void DoMethodExtended2(); //from MExampleInterfaceExtended2
private:
CImplementationClassExtended() {}
};
Implement REComSession::CreateImplementationL(),REComSession::GetExtendedInterfaceL(),REComSession::ManuallyReleaseExtendedInterfaceL() functions of the instantiation interface.
TAny* CImplementationClass::GetExtendedInterfaceL(TAny* aInstantiationInterface,
const TUid& aExtendedInterfaceUid,
TUint32& aBitFlags,
TAny*& aReleaseObject)
{
TAny* ret = NULL;
aBitFlags &= ~KReleaseRequiredMask; // clear release flag
switch (aExtendedInterfaceUid.iUid)
{
case 0x10009E44:
{
// release not required, so do not modify aBitFlags.
// re-cast Instantiation object as Extended Interface object
ret = static_cast<MExampleInterfaceExtended *> (static_cast<CImplementationClass *>(aObject));
break;
}
case 0x10009E45:
{
CImplementationClassExtended *classExt = CImplementationClassExtended::NewL();
aReleaseObject = classExt;
aBitFlags |= KReleaseRequiredMask; // Indicate release is required
// Multiple inheritance involved – Cbase and the M class. Must use
// either dynamic_cast or static_cast to add offset to the base pointer
ret = static_cast<MExampleInterfaceExtended2*>(classExt);
break;
}
}
return ret;
}
The plug-in framework releases the extended interface object when the
user destroys the instantiation interface object. Alternatively, if the framework
wants to release the extended interface earlier, they can call the REComSession::ManuallyReleaseExtendedInterfaceL()
void CImplementationClass::ReleaseExtendedInterface(TAny* aExtendedInterface, const TUid& aExtendedInterfaceUid)
{
switch (aExtendedInterfaceUid.iUid)
{
case 0x10009E45:
{
// this Extended Interface object require release.
CImplementationClassExtended* classExt = static_cast<CImplementationClassExtended*>(aReleaseObject);
delete classExt;
break;
}
}
}
The aInstanceKey parameter is returned by REComSession::CreateImplementationL().
It identifies the instantiation interface object instance. The aExtendedInterfaceUid
parameter identifies the extended interface required.
Export the instantiation functions into a TImplementationProxy3 table.
const TImplementationProxy3 KImplementationTable[] =
{
IMPLEMENTATION_PROXY_ENTRY3(0x10009E38, CImplementationClass::NewL, CImplementationClass::GetExtendedInterfaceL,CImplementationClass::ReleaseExtenedInterface)
};
EXPORT_C const TImplementationProxy3* ImplementationGroupProxy(TInt& aTableCount)
{
aTableCount = sizeof(KImplementationTable) / sizeof(TImplementationProxy3);
return KImplementationTable;
}
Export the release functions into a TImplementationProxy3 table.
void CImplementationClass::ReleaseExtendedInterface(TAny* aExtendedInterface, const TUid& aExtendedInterfaceUid)
{
switch (aExtendedInterfaceUid.iUid)
{
case 0x10009E45:
{
// this Extended Interface object require release.
CImplementationClassExtended* classExt = static_cast<CImplementationClassExtended*>(aReleaseObject);
delete classExt;
break;
}
}
}
To instantiate and use an extended interface, the plug-in user
must:
Identify plug-ins that
support the desired interface extensions using REComSession::ListImplementationsL().
IMPORT_C static void ListImplementationsL(TUid aInterfaceUid,
RExtendedInterfacesArray& aExtendedInterfaces,
const TEComResolverParams& aResolutionParameters,
RImplInfoPtrArray& aImplInfoArray);
The “aInterfaceUid” parameter specifies the instantiation
interface. All of the implementations returned in “aImplInfoArray” support
all the extensions listed in the “aExtendedInterfaces” parameter.
Select one from the
array and create an instantiation interface object.
Call REComSession::GetExtendedInterfaceL() API
to get an extended interface object.
IMPORT_C static TAny* GetExtenedInterfaceL(const TUid& aInstanceKey,
const TUid& aExtendedInterfaceUid);
The aInstanceKey parameter identifies the instantiation interface
object returned by REComSession::CreateImplementationL().
The example code depicts the above steps:
const TUid KExampleInterfaceUid = {0x10009DBB}; // the Instantiation Interface
const TUid KExtendedInterfaceUid1 = {0x10009E44};
const TUid KExtendedInterfaceUid2 = {0x10009E45};
// Set up extended interfaces UID list which form part of the resolution criteria.
RArray<TUid> extendedInterfaces;
CleanupClosePushL(extendedInterfaces);
extendedInterfaces.AppendL(KExtendedInterfaceUid1);
extendedInterfaces.AppendL(KExtendedInterfaceUid2);
// set up resolve parameter
_LIT8(KExampleImplementationData,"Extended Interface Example");
TEComResolverParams ResolverParams;
ResolverParams.SetDataType(KExampleImplementationData());
ResolverParams.SetGenericMatch(ETrue);
TUid instanceKey;
CExampleInterface* instantiateIf = static_cast<CExampleInterface*>(
REComSession::CreateImplementationL(KExampleInterfaceUid,
extendedInterfaces,
instanceKey,
ResolverParams) );
CleanupStack::PopAndDestroy(&extendedInterfaces);
CleanupStack::PushL(instantiateIf);
// May want to TRAP here if KErrNotSupported is handled, i.e. extension optional
MExampleInterfaceExtended2* ext2 = static_cast<MExampleInterfaceExtended2*>(
REComSession::GetExtendedInterfaceL(instanceKey, KExtendedInterfaceUid2));
instantiateIf->DoMethodL(); // access old interface function
ext2->DoMethodExtended2(); // access extension function
// Calling ManuallyReleaseExtendedInterface is optional. Do this
// if want to release extended object early.
REComSession::ManuallyReleaseExtendedInterface(instanceKey,KExtendedInterfaceUid2);
REComSession::DestroyedImplementation(instanceKey);
CleanupStack::PopAndDestroy(instantiateIf);
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.