John Bandhauer wrote:

> I think it is better to detect instances of your object using 
> QueryInterface rather than trust the cid. You can simply declare an iid 
> locally in your implmentation and have the QI method respond with a 
> pointer to your base object when QI'd for that iid. I think this is 
> safer and has no more overhead than what you propose.


Ah, this really reduces the amount of involved code
to 4 lines (.. nsIClassInfo is out) - nice!

I'm still using the cid, but now the actual casting is done
in a custom QI impl :


NS_IMETHODIMP
btCBuffer::QueryInterface (REFNSIID aIID, void** aInstancePtr)
{
// ..
     if ( aIID.Equals(this->GetCID()) ) {
         *aInstancePtr = this;
         return NS_OK;
     }
// ..


Now I just QI to the CID and get back the right downcast.


     void* _buf;
     rv = otherBuffer->QueryInterface (this->GetCID(), &_buf);

     // bail out: there's no btCBuffer behind !
     if (NS_FAILED(rv)) return NS_ERROR_FAILURE;

     // OK now, just a formal cast
     btCBuffer* otherBuffer = static_cast<btCBuffer*>(_buf);



Thanks,
Tobias.


-------------------
details ..


class btCBuffer : public btIBuffer
{
public:
     NS_DEFINE_STATIC_CID_ACCESSOR(BT_BUFFER_CID);
// ..snip


//  NS_IMPL_ISUPPORTS1_CI(btCBuffer, btIBuffer);

NS_IMPL_ADDREF(btCBuffer)
NS_IMPL_RELEASE(btCBuffer)


// modified QI impl for safe ifc->component downcast
NS_INTERFACE_MAP_BEGIN(btCBuffer)
     if ( aIID.Equals(this->GetCID()) ) {
         *aInstancePtr = this;
         return NS_OK;
     }
NS_INTERFACE_MAP_ENTRY(btIBuffer)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, btIBuffer)
NS_IMPL_QUERY_CLASSINFO(btCBuffer)
NS_INTERFACE_MAP_END



NS_IMPL_CI_INTERFACE_GETTER1(btCBuffer, btIBuffer)



the above custom QI impl expands to:

NS_IMETHODIMP
btCBuffer::QueryInterface (REFNSIID aIID, void** aInstancePtr)
{
     NS_ASSERTION(aInstancePtr,"QueryInterface requires a non-NULL 
destination!");
     if ( !aInstancePtr ) return NS_ERROR_NULL_POINTER;

     nsISupports* foundInterface;

     if ( aIID.Equals(this->GetCID()) ) {
         *aInstancePtr = this;
         return NS_OK;
     }

     if ( aIID.Equals(NS_GET_IID(btIBuffer)) )
         foundInterface = NS_STATIC_CAST(btIBuffer*, this);

     // .. snip


Reply via email to