XPCOM支持的每种语言都必须有自己的组件加载器。
XPCOM组件至少有三层,从里到外是:1)核心XPCOM对象。2)工厂代码 3)模块代码
核心XPCOM对象是实现你所需要的功能的对象,其他层是用来支持它,将它插入到XPCOM系统中的。一个单独的库可能有很多个这样的核心对象。
在核心对象层上面的是工厂层,工厂对象提供了XPCOM对象的基本抽象。
模块层在最外面,模块接口提供了另一种抽象—为工厂提供了抽象—并允许有多个工厂对象。从组件库的外部只有唯一的入口点,NSGetModule().这个入口点可以扇出任意工厂,从这些工厂创建出任意XPCOM对象
#include
<
stdio.h
>
#define
MOZILLA_STRICT_API
#include
"
nsIModule.h
"
#include
"
nsIFactory.h
"
#include
"
nsIComponentManager.h
"
#include
"
nsIComponentRegistrar.h
"
![](/Images/OutliningIndicators/None.gif)
static
const
nsIID kIModuleIID
=
NS_IMODULE_IID;
static
const
nsIID kIFactoryIID
=
NS_IFACTORY_IID;
static
const
nsIID kISupportsIID
=
NS_ISUPPORTS_IID;
static
const
nsIID kIComponentRegistrarIID
=
NS_ICOMPONENTREGISTRAR_IID;
![](/Images/OutliningIndicators/None.gif)
#define
SAMPLE_CID /
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{ 0x777f7150, 0x4a2b, 0x4301, /
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
{ 0xad, 0x10, 0x5e, 0xab, 0x25, 0xb3, 0x22, 0xaa}}
static
const
nsCID kSampleCID
=
SAMPLE_CID;
![](/Images/OutliningIndicators/None.gif)
class
Sample:
public
nsISupports
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
private:
nsrefcnt mRefCnt;
![](/Images/OutliningIndicators/InBlock.gif)
public:
Sample();
virtual ~Sample();
NS_IMETHOD QueryInterface(const nsIID &aIID, void **aResult);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
}
;
![](/Images/OutliningIndicators/None.gif)
Sample::Sample()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
:mRefCnt(0);
}
Sample::
~
Sample()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
}
![](/Images/OutliningIndicators/None.gif)
NS_IMETHODIMP Sample::QueryInterface(
const
nsIID
&
aIID,
void
**
aResult)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (aResult == NULL)
{
return NS_ERROR_NULL_POINTER;
}
*aResult = NULL;
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (aIID.Equals(kISupportsIID))
{
*aResult = (void *) this;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (aResult != NULL)
{
return NS_ERROR_NO_INTERFACE;
}
AddRef();
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt) Sample::AddRef()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
return ++mRefCnt;
}
NS_IMETHODIMP_(nsrefcnt) Sample::Release()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (--mRefCnt == 0)
{
delete this;
return 0;
}
return mRefCnt;
}
![](/Images/OutliningIndicators/None.gif)
//
factory implementation class for component
class
SampleFactory:
public
nsIFactory
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
private:
nsrefcnt mRefCnt;
public:
SampleFactory();
virtual ~SampleFactory();
NS_IMETHOD QueryInterface(const nsIID &aIID, void **aResult);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
NS_IMETHOD CreateInstance(nsISupports *aOuter, const nsIID & iid, void * *result);
NS_IMETHOD LockFactory(PRBool lock);
}
;
SampleFactory::SampleFactory()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
mRefCnt = 0;
}
SampleFactory::
~
SampleFactory()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
}
NS_IMETHODIMP SampleFactory::QueryInterface(
const
nsIID
&
aIID,
void
**
aResult)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (aResult == NULL)
{
return NS_ERROR_NULL_POINTER;
}
*aResult = NULL;
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (aIID.Equals(kISupportsIID))
{
*aResult = (void *) this;
}
else
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (aIID.Equals(kIFactoryIID))
{
*aResult = (void *) this;
}
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (aResult != NULL)
{
return NS_ERROR_NO_INTERFACE;
}
AddRef();
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt) SampleFactory::AddRef()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
return ++mRefCnt;
}
NS_IMETHODIMP_(nsrefcnt) SampleFactory::Release()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (--mRefCnt == 0)
{
delete this;
return 0;
}
return mRefCnt;
}
NS_IMETHODIMP SampleFactory::CreateInstance(nsISupports
*
aOuter,
const
nsIID
&
iid,
void
*
*
result)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
if (!result)
return NS_ERROR_INVALID_ARG;
Sample* sample = new Sample();
if (!sample)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = sample->QueryInterface(iid, result);
if (NS_FAILED(rv))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
*result = nsnull;
delete sample;
}
return rv;
}
NS_IMETHODIMP SampleFactory::LockFactory(PRBool
lock
)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//
Module implementation
class
SampleModule :
public
nsIModule
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
public:
SampleModule();
virtual ~SampleModule();
// nsISupports methods:
NS_IMETHOD QueryInterface(const nsIID & uuid, void * *result);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
// nsIModule methods:
NS_IMETHOD GetClassObject(nsIComponentManager *aCompMgr, const nsCID & aClass, const nsIID & aIID,void * *aResult);
NS_IMETHOD RegisterSelf(nsIComponentManager *aCompMgr, nsIFile *aLocation, const char *aLoaderStr,const char *aType);
NS_IMETHOD UnregisterSelf(nsIComponentManager *aCompMgr, nsIFile *aLocation, const char *aLoaderStr);
NS_IMETHOD CanUnload(nsIComponentManager *aCompMgr, PRBool *_retval);
private:
nsrefcnt mRefCnt;
}
;
//
----------------------------------------------------------------------
SampleModule::SampleModule()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
mRefCnt = 0;
}
SampleModule::
~
SampleModule()
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
}
//
nsISupports implemention
NS_IMETHODIMP_(nsrefcnt) SampleModule::AddRef(
void
)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
++mRefCnt;
return mRefCnt;
}
NS_IMETHODIMP_(nsrefcnt) SampleModule::Release(
void
)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
--mRefCnt;
if (mRefCnt == 0)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
mRefCnt = 1; /**//* stabilize 这里为什么要设置为1呢?*/
delete this;
return 0;
}
return mRefCnt;
}
NS_IMETHODIMP SampleModule::QueryInterface(REFNSIID aIID,
void
**
aInstancePtr)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
if ( !aInstancePtr )
return NS_ERROR_NULL_POINTER;
nsISupports* foundInterface;
if ( aIID.Equals(kIModuleIID) )
foundInterface = (nsIModule*) this;
else if ( aIID.Equals(kISupportsIID) )
foundInterface = (nsISupports*) this;
else
foundInterface = 0;
if (foundInterface)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
foundInterface->AddRef();
*aInstancePtr = foundInterface;
return NS_OK;
}
*aInstancePtr = foundInterface;
return NS_NOINTERFACE;
}
//
Create a factory object for creating instances of aClass.
NS_IMETHODIMP SampleModule::GetClassObject(nsIComponentManager
*
aCompMgr,
const
nsCID
&
aClass,
const
nsIID
&
aIID,
void
**
result)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
if (!kSampleCID.Equals(aClass))
return NS_ERROR_FACTORY_NOT_REGISTERED;
if (!result)
return NS_ERROR_INVALID_ARG;
SampleFactory* factory = new SampleFactory();
if (!factory)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = factory->QueryInterface(aIID, result);
if (NS_FAILED(rv))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
*result = nsnull;
delete factory;
}
return rv;
}
NS_IMETHODIMP SampleModule::RegisterSelf(nsIComponentManager
*
aCompMgr,nsIFile
*
aPath,
const
char
*
registryLocation,
const
char
*
componentType)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
nsIComponentRegistrar* compReg = nsnull;
nsresult rv = aCompMgr->QueryInterface(kIComponentRegistrarIID, (void**)&compReg);
if (NS_FAILED(rv))
return rv;
rv = compReg->RegisterFactoryLocation(kSampleCID,"Sample Class",nsnull,aPath,registryLocation,componentType);
compReg->Release();
return rv;
}
NS_IMETHODIMP SampleModule::UnregisterSelf(nsIComponentManager
*
aCompMgr,nsIFile
*
aPath,
const
char
*
registryLocation)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
nsIComponentRegistrar* compReg = nsnull;
nsresult rv = aCompMgr->QueryInterface(kIComponentRegistrarIID, (void**)&compReg);
if (NS_FAILED(rv))
return rv;
rv = compReg->UnregisterFactoryLocation(kSampleCID, aPath);
compReg->Release();
return rv;
}
NS_IMETHODIMP SampleModule::CanUnload(nsIComponentManager
*
aCompMgr, PRBool
*
okToUnload)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
*okToUnload = PR_FALSE; // we do not know how to unload.
return NS_OK;
}
extern
"
C
"
NS_EXPORT nsresult NSGetModule(nsIComponentManager
*
servMgr,nsIFile
*
location,nsIModule
**
return_cobj)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
nsresult rv = NS_OK;
// Create and initialize the module instance
SampleModule *m = new SampleModule();
if (!m)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return NS_ERROR_OUT_OF_MEMORY;
}
// Increase refcnt and store away nsIModule interface to m in return_cobj
rv = m->QueryInterface(kIModuleIID, (void**)return_cobj);
if (NS_FAILED(rv))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
delete m;
}
return rv;
}