《XPCOM组件开发》笔记(三)

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"

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;

#define SAMPLE_CID \
0x777f71500x4a2b0x4301, \
0xad0x100x5e0xab0x250xb30x220xaa}}

static const nsCID kSampleCID = SAMPLE_CID;

class Sample: public nsISupports 
{
private:
    nsrefcnt mRefCnt;

public:
    Sample();
    
virtual ~Sample();
    NS_IMETHOD QueryInterface(
const nsIID &aIID, void **aResult);
    NS_IMETHOD_(nsrefcnt) AddRef(
void);
    NS_IMETHOD_(nsrefcnt) Release(
void);
}
;

Sample::Sample()
{
    :mRefCnt(
0);
}

Sample::
~Sample()
{
}


NS_IMETHODIMP Sample::QueryInterface(
const nsIID &aIID,void **aResult)
{
    
if (aResult == NULL) {
        
return NS_ERROR_NULL_POINTER;
    }

    
*aResult = NULL;
    
if (aIID.Equals(kISupportsIID)) {
    
*aResult = (void *this;
    }

    
if (aResult != NULL) {
    
return NS_ERROR_NO_INTERFACE;
    }

    AddRef();
    
return NS_OK;
}

NS_IMETHODIMP_(nsrefcnt) Sample::AddRef()
{
    
return ++mRefCnt;
}

NS_IMETHODIMP_(nsrefcnt) Sample::Release()
{
    
if (--mRefCnt == 0{
    delete 
this;
    
return 0;
    }

    
return mRefCnt;
}


// factory implementation class for component
class SampleFactory: public nsIFactory
{
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()
{
    mRefCnt 
= 0;
}

SampleFactory::
~SampleFactory()
{
}

NS_IMETHODIMP SampleFactory::QueryInterface(
const nsIID &aIID,void **aResult)
{
    
if (aResult == NULL) {
    
return NS_ERROR_NULL_POINTER;
    }

    
*aResult = NULL;
    
if (aIID.Equals(kISupportsIID)) {
    
*aResult = (void *this;
    }

    
else
    
if (aIID.Equals(kIFactoryIID)) {
    
*aResult = (void *this;
    }

    
if (aResult != NULL) {
    
return NS_ERROR_NO_INTERFACE;
    }

    AddRef();
    
return NS_OK;
}

NS_IMETHODIMP_(nsrefcnt) SampleFactory::AddRef()
{
    
return ++mRefCnt;
}

NS_IMETHODIMP_(nsrefcnt) SampleFactory::Release()
{
    
if (--mRefCnt == 0{
    delete 
this;
    
return 0;
    }

    
return mRefCnt;
}

NS_IMETHODIMP SampleFactory::CreateInstance(nsISupports 
*aOuter, const nsIID & iid, void * *result)
{
    
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)) 
    
{
        
*result = nsnull;
        delete sample;
    }

    
return rv;
}

NS_IMETHODIMP SampleFactory::LockFactory(PRBool 
lock)
{
    
return NS_ERROR_NOT_IMPLEMENTED;
}

// Module implementation
class SampleModule : public nsIModule
{
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()
{
    mRefCnt 
= 0;
}

SampleModule::
~SampleModule()
{
}

// nsISupports implemention
NS_IMETHODIMP_(nsrefcnt) SampleModule::AddRef(void)
{
    
++mRefCnt;
    
return mRefCnt;
}

NS_IMETHODIMP_(nsrefcnt) SampleModule::Release(
void)
{
    
--mRefCnt;
    
if (mRefCnt == 0
    
{
        mRefCnt 
= 1/* stabilize 这里为什么要设置为1呢?*/
        delete 
this;
        
return 0;
    }

    
return mRefCnt;
}

NS_IMETHODIMP SampleModule::QueryInterface(REFNSIID aIID, 
void** aInstancePtr)
{
    
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) 
    
{
        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)
{
    
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)) 
    
{
        
*result = nsnull;
        delete factory;
    }

    
return rv;
}

NS_IMETHODIMP SampleModule::RegisterSelf(nsIComponentManager 
*aCompMgr,nsIFile* aPath,const char* registryLocation,const char* componentType)
{
    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)
{
    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)
{
    
*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)
{
    nsresult rv 
= NS_OK;
    
// Create and initialize the module instance
    SampleModule *= new SampleModule();
    
if (!m) 
    
{
        
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)) 
    
{
        delete m;
    }

    
return rv;
}

posted on 2008-06-02 15:25  Phinecos(洞庭散人)  阅读(1802)  评论(1编辑  收藏  举报

导航