One of the principles and implementation of COM

Source: Internet
Author: User
Tags assert volatile
one of the principles and implementation of COM


COM component is actually a special object system, follow a unified standard, so that each software can access the object in some way, can do component calls. COM is the unified standard-invoking COM components through interfaces. An interface is the only thing that a COM component can be perceived by the outside world.

Interfaces for all interfaces inherit from IUnknown, implementing interface queries and reference counts. Contains 3 methods:

  Interface   IUnknown
  {
          virtual   HRESULT   _stdcall   QueryInterface ([In]refiid IID, [out] void * * * PPV) =0;  
          Virtual   ULONG   _stdcall   AddRef (void) =0;  
          Virtual   ULONG   _stdcall release   (void) =0;  
  }
QueryInterface is responsible for obtaining pointers to the other interfaces of the component.
Addref/release is responsible for managing the lifetime of the component-reference count +1/-1.


I implemented Cross-platform COM, also defined a similar IUnknown interface, I call it: iuniversal, defined as follows:

/** * IUniversal.h * Iuniversal is a variant from IUnknown * Refer: * <<inside com>> * * Init Created: 2016-06-10 * Last updated:2016-06-10 * * * #ifndef iuniversal_h #define IUNIVERSAL_H #include "Platform.h" #define Iid_iu

    Niversal ((iid_t) ( -1)) interface Iuniversal {static const iid_t IID = ((iid_t) (-1));
    Virtual lresult_t query (iid_t iid, void **ppvout) = 0;
    Virtual unsigned long retain (void) = 0;
Virtual unsigned long release (void) = 0;


};

Class Universalimpl {private:refcount_t _REFC;
    Public:universalimpl (): _REFC (1) {} virtual ~universalimpl () {}///Iuniversal//


    Virtual lresult_t query (iid_t iid, void **PPV) = 0;
    Virtual unsigned long retain (void) {return __interlock_inc (&AMP;_REFC);
            Virtual unsigned long release (void) {if (__interlock_dec (&AMP;_REFC) = = 0) {Delete this;
        return 0;
    return _REFC;


}
}; #endIf/* Iuniversal_h * 

Where Platform.h is defined as follows:

/** * Platform.h * * * Init created:2016-06-10 * Last updated:2016-06-10/#ifndef platform_h #define PLATFORM_H #if D efined _msc_ver | |  WIN32 #ifndef os_platform_win #define Os_platform_win #endif #endif #ifdef os_platform_win #include <windows.h> #include <process.h> #else #include <pthread.h> #include <unistd.h> #endi


F #ifndef Interface #define INTERFACE struct #endif/** * Interface IID/typedef unsigned int iid_t;

/** * Long result/typedef long LRESULT_T; #define LRES_SUCCESS 0 #define LRES_ERROR ( -1) #define LRES_E_OUTMEMORY ( -4) #define LRES_E_
    Nointerface ( -11)/** * Ref count type */#ifdef os_platform_win typedef volatile unsigned long refcount_t; #define __INTERLOCK_INC (ADD) interlockedincrement (add) #define __INTERLOCK_DEC (sub) InterlockedDecrement (sub) #el
    SE typedef volatile size_t refcount_t; #define __INTERLOCK_INC (ADD) __sync_add_and_fetcH (Add, 1) #define __INTERLOCK_DEC (sub) __sync_sub_and_fetch (sub, 1) #endif #endif/* Platform_h * 

Any C + + object that wants to be COM must inherit from Iuniversal, and because Universalimpl implements a default iuniversal, it can be inherited directly from Universalimpl.

For example, we define the following component entity, whose interface is defined as follows:

Interface Entityinterface:iuniversal
{
    static const iid_t IID = ((iid_t) 0x00f001);

    virtual void addcomponent (abstractcomponent * component) = 0;

    virtual void removecomponent (abstractcomponent * component) = 0;

    virtual void removeallcomponents () = 0;
};

The implementation of the component Entity is as follows:

/** * Entity.h * * Refer: * http://www.richardlord.net/blog/what-is-an-entity-framework * http://blog.csdn.net/i_dovel emon/article/details/30250049 * http://blog.csdn.net/zhao_92221/article/details/46629553 * http://blog.csdn.net/ ubuntu64fan/article/details/8839778 * Init created:2016-05-30 * Last updated:2016-06-08/#ifndef entity_h #define EN Tity_h #include ". /entityinterface.h "#include". /componentmanager.h "#include <stdio.h> #include <assert.h> #include". /.. /.. /common/hashmap.h "#include". /.. /..


/common/dhlist.h "#include <memory> #include <vector> using namespace std;


Namespace ECS {class Entitymanager;

    Class Entity:public Universalimpl, public entityinterface {friend Class Entitymanager;

    static const int comps_hashsize = 0x10;

        Entity () {printf ("entity\n");

        Init_list_head (&list1_comps); for (int hash = 0; hash <= comps_hashsize; hash++) {Init_hlist_head (&hlist_comps[hash]);

        } public:virtual ~entity () {printf ("~entity\n");
    Removeallcomponents (); Public://Create function//static lresult_t CreateInstance (Entityinterface **PPV) {Entityinte
        Rface * p = (entityinterface *) new Entity ();
            if (p) {*PPV = P;
        return lres_success;
            else {*PPV = 0;
        return lres_e_outmemory; }//Iuniversal//Virtual lresult_t query (iid_t iid, void **PPV) {if (IID = = Iuniversal::iid ||
        IID = = entityinterface::iid) {*PPV = Static_cast<entityinterface *> (this);
            else {*PPV = 0;
        return lres_e_nointerface;
        } reinterpret_cast<iuniversal*> (*PPV)->retain ();
    return lres_success;
    Virtual unsigned long retain (void) {return universalimpl::retain (); Virtual unsigned long release (void) {return universalimpl::release (); }//Entityinterface//virtual void addcomponent (Abstractcomponent * component) {Component_type Co

        Mptype = Component->getcomponenttype ();
    List_add (&component->i_list, &list1_comps);
        virtual void removecomponent (Abstractcomponent * component) {} virtual void removeallcomponents () {

        struct List_head *list, *node; List_for_each_safe (list, node, &list1_comps) {class abstractcomponent * p = list_entry (list, class Abstra
            Ctcomponent, i_list);
            List_del (list);
        Delete (p);
    }} private:struct List_head i_list;

    struct Hlist_node i_hash;
    * * Components list and hlist * * struct list_head list1_comps;
struct Hlist_head hlist_comps[comps_hashsize + 1];

}; }; * Namespace ECS */#endif/* entity_h * *

Such a COM system is initially embryonic. We also need a smart pointer object to help us use the Component object when we use it. I define this smart interface pointer as follows:

/** * SIPtr.h * Smart Interface pointer * * Use:siptr<ix, iidix> Spix; * Don't use with iuniversal;  Siptr<iuniversal, iidiuniversal> * would not compile. 
Instead, use Iuniversalsptr. * * Refer: * <<inside com>> * * Init created:2016-06-10 * Last updated:2016-06-10/#ifndef siptr_h #defi Ne siptr_h #include "IUniversal.h" #include <assert.h> template <class t> class Siptr {public://Co
    Nstructors siptr () {m_pi = 0;
        } siptr (t* lp) {M_PI = LP;
        if (M_PI) {m_pi->retain ();
        } siptr (iuniversal* pI) {m_pi = 0;
        if (PI) {pi->query (t::iid, (void * *) & M_PI);
    }//destructor ~siptr () {release ();
            }//Reset void release () {if (M_PI) {t* pold = M_PI;
            M_PI = 0;
        Pold->release (); }//Attach to an existingInterface (does not retain) void attach (T * PI) {if (M_pi!= pI) {iuniversal* pold = M_PI;

            M_PI = PI;
            if (pold) {//release of the Old Interface Pold->release ();
        }}//Detach The interface (does not release) t* Detach () {t* pold = M_PI;
        M_PI = 0;
    return pold;
    }//conversion operator t* () {return m_pi;
        }//Pointer operations t& operator* () {assert (M_PI);
    return * M_PI;
        } t** operator& () {assert (!M_PI);
    Return &m_pI;
        } t* operator-> () {assert (M_PI);
    return M_PI; }//assignment from the same interface t* operator= (t* pi) {if (m_pi!= pi) {//Save Curr

            ENT value iuniversal* pold = (iuniversal *) M_pi;

            Assign new Value m_pi = PI; if (m_PI) {m_pi->retain ();
            } if (Pold) {//release of the Old Interface Pold->release ();
    } return M_PI; }//Assignment from another interface t* operator= (iuniversal* PI) {//Save value Iuni
        versal* pold = M_PI;

        M_PI = 0; Query for Correct interface if (PI) {lresult_t hr = Pi->query (T::iid_interface, (void**) ;
            M_PI);
        ASSERT (hr = = lres_success && m_pi);
        } if (Pold) {//release old pointer Pold->release (); 
    return M_PI; }//BOOL functions bool operator!
    () {return M_PI false:true;
    }//Requires a compiler that supports BOOL operator BOOL () const {return m_pi? true:false;
    }//Interface ID iid_t iid () {return t::iid; 
  } Private:  pointer variable t* M_PI;


}; /** * Iuniversalptr is a smart interface for Iuniversal */class Iuniversalptr {public://Constructors Iuniversa
    Lptr () {m_pi = 0;
        } iuniversalptr (iuniversal* lp) {M_PI = LP;
        if (M_PI) {m_pi->retain ();
    }//destructor ~iuniversalptr () {release ();
            }//Reset void release () {if (M_PI) {iuniversal* pold = M_PI;
            M_PI = 0;
        Pold->release ();
    }//conversion operator iuniversal* () {return (iuniversal*) M_pi;
        }//Pointer operations iuniversal& operator* () {assert (M_PI);
    return *M_PI;
        } iuniversal** operator& () {assert (!M_PI);
    Return &m_pI;
        } iuniversal* operator-> () {assert (M_PI);
    return M_PI;
    }//Assignment iuniversal* operator= (iuniversal* PI) {    if (m_pi!= PI) {//Save current value iuniversal* pold = M_PI;

            Assign new Value m_pi = PI;
            if (M_PI) {m_pi->retain ();
            } if (Pold) {//release of the Old Interface Pold->release ();
    } return M_PI; }//Boolean functions bool operator!
    () {return M_PI false:true;
    } operator bool () const {return m_pi? true:false;
Private://pointer variable iuniversal* M_PI; 

};
 #endif/* Siptr_h * *

Using Entity is simple:

void Testentityinterface ()
{
    siptr<entityinterface>spentity;

    Entity::createinstance (&spentity);

    Spentity->addcomponent (...);
}


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.