COM组件技术在Linux C++下的使用例子

COM的接口
 
一. 接口概念的出现
承接COM的目的,现在需要将重用的COM对象相互关联在一起,那么有什么好方法呢?
(1)OO中使用public成员来让外界和内部对象进行数据交互。COM中更进一步,只能使用public的成员函数。因为直接访问对象内存不利于实行低耦合的模型,所以数据的交互都应该使用函数调用。
(2)一个COM对象可以提供多个函数供外部调用,这是很自然的。
(3}类似于OO中的多态,一个函数可以被多个COM对象实现,这样调用方可以方便统一的实现所需的功能。
 
在C++中,我们用public成员函数来提供对外接口,用虚函数来实现多态。因此,对COM的要求,实际上就是需要一个虚基类,其定义了一组函数,然后COM类来继承这个基类,从而也拥有了这组函数。而当COM类要有多个供外界调用的函数时,可以把这些函数分别定义在一些虚基类中,然后再用多重继承的方法使COM类拥有这些函数。
尽管对每个函数都去定义一个虚基类也毫无不可,但很多时候这样分散并不利于管理这些函数。因此常常把一组功能有关联的函数合并在一个虚基类里面。
这个只拥有一组虚函数的基类就是COM中的接口,其目的是定义COM对象被访问的方法。每个接口都被一个GUID标识,称为IID。

二. 接口的本质
如果把C++描述转化成二进制代码的话,就会发现接口本质上就是vtable,位于COM对象的开头,指向一组函数指针。那么为什么是接口而不是单个函数被GUID表识,从而能够被准确定位呢?
还是参考C++编写的COM对象在内存中的二进制表示吧。此时其开头是一列指针,分别对应于多重继承而来的各个接口,然后每个指针指向一个函数指针数组,就是对应于各个接口的成员函数。因此,接口和对象在内存中是平级的!C++实现多重继承时只不过是罗列了多个虚函数表,然后调用函数时再根据具体使用的指针类型,给指向对象的指针加上某个偏移量得到该类型对应的虚函数表,再找到具体的函数。显然指针在接口这一层时可以很自如的通过偏移得到其它的接口指针以及对象指针——而一旦得到具体函数指针后,就很难回头了。
 
COM规定了一个函数QueryInterface(),用来得到接口的指针。并把QueryInterface()放入接口类IUnknown中,而且规定所有的接口都要从IUnknown继承,换句话说,所有的接口都要实现IUnknown类定义的那几个函数。QueryInterface()的引入可以让调用方在使用COM对象时,能够在COM对象提供的接口之间自由的来回切换。当然,正如上面所述,其本质只是指向接口的指针做了偏移而已。
 
三. 接口的使用方法
首先,所有COM对象的接口都继承自IUnknown,而IUnknown中是有QueryInterface()函数的。
再次,COM对象的开头就是第一个接口的vtable,所以指向COM对象的指针同时也是指向第一个接口的指针。并且,由于接口都是继承自IUnknown,因此这个指针也一定是指向IUnknown的指针。这样一来的话就能够顺利调用QueryInterface(),得到某个接口的指针了。
然后,不管任何时候,只要有某接口的指针,就可以接着用QueryInterface()来得到该COM对象拥有的其它接口指针。
 
类厂以及COM对象的构造
二. 类厂概念的引入
类厂(ClassFactory)这个名词其实有点迷惑性,因为这个东西实际上应该叫对象工厂。类厂也是一个普通的COM对象,它有一个特殊的接口IClassFactory,这个接口的一个函数CreateInstance()能够生成COM对象,并返回其需要的接口。
如果把C++中的概念平移过来,就会发现类厂的作用本质上就是那个被C++编译器隐藏了的new。在COM中没有类定义,自然也没有new,要想生成COM对象,只能靠COM类的规范。类厂就实现了从COM类规范到COM对象的过程。
 
当用C++实现COM的时候,往往在类厂也就是new出来一个对象,然后做一个QueryInterface()得到接口指针。表面上看,中间多了类厂这么一层有点多此一举,实际上这里隐含了根据抽象的COM类在内存中生成COM对象的步骤,绝非可有可无的。
 
三. 类厂的返回值
在前面说过COM中以COM对象为单位实行重用,COM对象通过接口和外界交互,COM对象的接口之间可以通过偏移来实现跳转。并且,从二进制上看,指向COM对象的指针就是指向COM对象继承的第一个接口的指针。所以,在COM中并不需要一个指向COM对象的指针,而只需要指向该COM对象的某一个接口的指针。因此类厂最后是返回COM对象的一个接口指针来告诉用户,这个COM对象已经生成了。当然,这个接口指针的表识(IID)需要用户提供。

COM对象的调用
AddRef和Release
 
一. IUnknown接口
按照COM标准,所有的COM接口的前三个函数都必须是IUnknown接口的那三个函数:QueryInterface(),AddRef()和Release()。如果用C++表述的话,就是所有的COM接口都必须从IUnknown这个虚基类继承而来。
QueryInterface()的作用前面已经说过了,是根据IID查询当前COM对象是否有此接口,并返回接口指针。那么AddRef()和Release()呢?
按照字面的意思,AddRef()的意思就是说增加当此接口被引用的次数,而Release()则是释放。实际上也差不多就是这么回事……虽然Release()表面上看起来起一个SubRef()的名字能够更加和AddRef()匹配一点。
 
二. COM对象的创建过程和引用计数的需求
如果按照一般的思想,COM对象被创建后,大家自由使用就是了,为了什么非要引入AddRef()和Release()函数?其实这里涉及到的问题主要是COM对象的生存期问题。一个COM对象何时被谁创建?何时又被谁释放呢?
最自然的回答肯定是需要时创建以实现应用,不需要时释放以节约系统资源。但是这里实现就有很多问题:首先,按照前面所述,客户并不真正的了解COM对象,它只能提供CLSID来定位COM对象,提供IID来查询接口,然后能做的就是利用接口实现功能。在Windows的COM库中,用CoCreateInstance()函数来封装客户端的调用,然后CoCreateInstance()根据CLSID在注册表中找到实现该对象保存的文件,再根据调用方式的不同(进程内/进程外)将该文件装载入内存,创建类厂,然后用类厂的CreateInstance()接口创建COM对象并返回IID指定的接口。这一连串的工作分的很细,主要的目的就是用中间层,比如COM库函数和标准IClassFactory接口等隔开用户和具体COM对象,实现更好地封装。
既然如此,具体生成COM对象的并不是客户端而是COM组件中和COM对象对应的类厂对象。因此,释放或者说从内存中卸载COM对象的任务也不能是客户端完成。而在COM组件中,类厂只管生成,那么释放的任务就只能交给COM对象自己完成了。
 
所以,最后的要求就变成了COM对象自己需要知道什么时候能够释放自身,那么就需要有一个量来表示现在到底又多少用户在使用此COM对象,这就是引用计数了。
三. 引用计数的实现
实现引用计数的方法很简单,用一个全局的变量来保存计数,多一个引用时加一,少一个引用时减一。COM规定当创建COM对象时先把计数从0加到1,然后加加减减,直到计数变到0,说明已经没有用户使用该COM对象,那么这个就可以释放资源了。
由于客户端只能对接口操作,因此AddRef()和Release()需要保证能够在任何接口下都能调用,包括IUnknown。这样一来,这两个函数和QueryInterface()并列成为IUnknown的三个成员也就顺理成章了。
这里还有一些小问题。比如说是针对COM对象整体计数呢,还是针对各个接口计数?COM标准没有硬性规定,但是作为COM对象的使用者,客户端必须考虑到不同情况,所以必须是调用增加或减少引用的那个接口的AddRef()和Release()。


COM实现的技术,主要是C++的虚函数、多继承以及动态链接库(DLL)技术。
COM组件的实现:
项目代码如下;

类厂头文件
链表类厂 头文件 ListClassFactory.h
/*************************************************************************
    > File Name: ListClassFactory.h 
    > Created Time: 2016年09月12日 23时53分23秒 CST
 ************************************************************************/
 
#ifndef _LIST_CLASS_FACTORY_H
#define _LIST_CLASS_FACTORY_H
 
#include "../../ibasecom/IUnknown.h"
#include "../../ibasecom/IClassFactory.h"
 
 
class ListClassFactory : public IClassFactory
{
private:
    ULONG m_cRef;
public:
    ListClassFactory(){LogD("ListClassFactory: ","===ListClassFactory()===");}
    ~ListClassFactory(){LogD("ListClassFactory: ","====~ListClassFactory()=======");}
private:
    virtual LONG  QueryInterface(const IID& iid, void** ppv);
    virtual ULONG AddRef();
    virtual ULONG Release();
    virtual IUnknown* CreateInstance(const IID& iid,void**ppv);
 
};
 
#ifdef __cplusplus
extern "C"
{
#endif
 
IUnknown* DllGetClassObject(const CLSID &clsid, const IID &iid, void **ppv);
IUnknown* (*g_CoCreate)(const IID& iid,void** ppv) = NULL;
 
#ifdef __cplusplus
}
#endif
 
#endif

Vector类厂 头文件 VectorClassFactory.h
/*************************************************************************
    > File Name: VectorClassFactory.h 
    > Created Time: 2016年08月26日 23时50分23秒 CST
 ************************************************************************/
 
#ifndef _VECTOR_CLASS_FACTORY_H
#define _VECTOR_CLASS_FACTORY_H
 
#include "../../ibasecom/IUnknown.h"
#include "../../ibasecom/IClassFactory.h"
 
 
class VectorClassFactory : public IClassFactory
{
private:
    ULONG m_cRef;
public:
    VectorClassFactory(){LogD("VectorClassFactory: ","===VectorClassFactory()===");}
    ~VectorClassFactory(){LogD("VectorClassFactory: ","====~VectorClassFactory()=======");}
private:
    virtual LONG  QueryInterface(const IID& iid, void** ppv);
    virtual ULONG AddRef();
    virtual ULONG Release();
    virtual IUnknown* CreateInstance(const IID& iid,void**ppv);
 
};
 
#ifdef __cplusplus
extern "C"
{
#endif
 
IUnknown* DllGetClassObject(const CLSID &clsid, const IID &iid, void **ppv);
IUnknown* (*g_CoCreate)(const IID& iid,void** ppv) = NULL;
 
#ifdef __cplusplus
}
#endif
 
#endif


类厂实现文件 ListClassFactory.cpp
/*************************************************************************
    > File Name: ListClassFactory.cpp
    > Created Time: 2016年09月12日 23时58分21秒
************************************************************************/
 
#include <dlfcn.h>
#include <stdlib.h>
#include "../include/ListClassFactory.h"
#include "../../log/util.h"
 
#define TAG "ListClassFactory"
 
IUnknown* ListClassFactory::CreateInstance(const IID& iid,void**ppv)
{
    LogD(TAG,"CreateComInstance start");
    IUnknown*       pUnknown;
    pUnknown = (*g_CoCreate)(iid,ppv);
    LogD(TAG,"CreateComInstance end");
 
    return pUnknown;
}
 
LONG ListClassFactory::QueryInterface(const IID& iid, void** ppv)
{
    LogD(TAG,"enter QueryInterface");
    if(iid == IID_ICLSFACTORY)
    {
        LogD(TAG,"Return Pointer to IClassFactory");
        *ppv = static_cast<IClassFactory*>(this);
    }
    else if(iid == IID_CLS_IUnknown)
    {
        LogD(TAG,"Return Pointer to IUnknown");
        *ppv = static_cast<IUnknown*>(this);
    }
    else
    {
        LogD(TAG,"Interface is not surpport!");
        *ppv = NULL;
        return E_NOINTERFACE;
    }
    reinterpret_cast<IUnknown*>(*ppv)->AddRef();
                                                
    return S_OK;
}
 
ULONG ListClassFactory::AddRef()
{
    m_cRef++;
    LogD(TAG,"AddRef,m_cRef: %d\n",m_cRef);
}
 
ULONG ListClassFactory::Release()
{
    LogD(TAG,"Release,m_cRef: %d\n",m_cRef);
    if((--m_cRef) == 0)
    {
        delete this;
        return 0;
    }
    return m_cRef;
}
 
IUnknown* DllGetClassObject(const CLSID &clsid, const IID &iid, void **ppv)
{
    LogD(TAG,"enter DllGetClassObject");
    if(clsid == CLSID_LIST_FACTORY)
    {
        LogD(TAG,"Return Pointer to ClassFactory");
        IUnknown* pI = static_cast<IClassFactory*>(new ListClassFactory);
        pI->AddRef();
        LogD(TAG,"ClassFactory create successful");
        LONG hr = pI->QueryInterface(iid,ppv);
        if(hr == S_OK)
        {
            pI->Release();
        }
        return pI;
    }
    else
    {
        LogD(TAG,"the ClassFactory is not support!");
        *ppv = NULL;
        return NULL;
    }
}
 

类厂实现文件 VectorClassFactory.cpp
/*************************************************************************
    > File Name: VectorClassFactory.cpp
    > Created Time: 2016年08月26日 23时55分20秒
************************************************************************/
 
#include <dlfcn.h>
#include <stdlib.h>
#include "../include/VectorClassFactory.h"
#include "../../log/util.h"
 
#define TAG "VectorClassFactory"
 
IUnknown* VectorClassFactory::CreateInstance(const IID& iid,void**ppv)
{
    LogD(TAG,"CreateComInstance start");
    IUnknown*       pUnknown;
    pUnknown = (*g_CoCreate)(iid,ppv);
    LogD(TAG,"CreateComInstance end");
 
    return pUnknown;
}
 
LONG VectorClassFactory::QueryInterface(const IID& iid, void** ppv)
{
    LogD(TAG,"enter QueryInterface");
    if(iid == IID_ICLSFACTORY)
    {
        LogD(TAG,"Return Pointer to IClassFactory");
        *ppv = static_cast<IClassFactory*>(this);
    }
    else if(iid == IID_CLS_IUnknown)
    {
        LogD(TAG,"Return Pointer to IUnknown");
        *ppv = static_cast<IUnknown*>(this);
    }
    else
    {
        LogD(TAG,"Interface is not surpport!");
        *ppv = NULL;
        return E_NOINTERFACE;
    }
    reinterpret_cast<IUnknown*>(*ppv)->AddRef();
                                                
    return S_OK;
}
 
ULONG VectorClassFactory::AddRef()
{
    m_cRef++;
    LogD(TAG,"AddRef,m_cRef: %d\n",m_cRef);
}
 
ULONG VectorClassFactory::Release()
{
    LogD(TAG,"Release,m_cRef: %d\n",m_cRef);
    if((--m_cRef) == 0)
    {
        delete this;
        return 0;
    }
    return m_cRef;
}
 
IUnknown* DllGetClassObject(const CLSID &clsid, const IID &iid, void **ppv)
{
    LogD(TAG,"enter DllGetClassObject");
    if(clsid == CLSID_IVECTORFACTORY)
    {
        LogD(TAG,"Return Pointer to ClassFactory");
        IUnknown* pI = static_cast<IClassFactory*>(new VectorClassFactory);
        pI->AddRef();
        LogD(TAG,"ClassFactory create successful");
        LONG hr = pI->QueryInterface(iid,ppv);
        if(hr == S_OK)
        {
            pI->Release();
        }
        return pI;
    }
    else
    {
        LogD(TAG,"the ClassFactory is not support!");
        *ppv = NULL;
        return NULL;
    }
}
 

组件头文件  IcstashBase.h
/*************************************************************************
    > File Name: IcstashBase.h
    > Created Time: 2016年08月26日 22时30分03秒 CST
 *************************************************************************/
 
 
#ifndef _ICSTASH_BASE__
#define _ICSTASH_BASE__
 
#include "../../ibasecom/IUnknown.h"
#include "../../log/util.h"
 
#define CAPACIPY 10
//typedef double T;
typedef int T;
 
interface IcstashBase : public IUnknown  
{
public:
    IcstashBase(){ LogD("IcstashBase","IcstashBase() this: %p\n",this); }
    virtual ~IcstashBase(){ LogD("IcstashBase","~IcstashBase() this: %p\n",this); }
    virtual void travel()const = 0;
    virtual void clear() = 0;
    virtual int count()const = 0;
    virtual bool isEmpty()const = 0;
};
 
extern "C"
{
    const IID IID_IBASE = {0x32bb8321, 0xb41b, 0x11cf,{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
    const IID IID_COM_IUnknown = {0x32bb8324, 0xb41b, 0x11cf,{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
}
 
#endif


链表组件 接口文件 IcstashList.h
/*************************************************************************
   > File Name: IcstashList.h
   > Created Time: 2016年09月12日 22时10分03秒 CST
 *************************************************************************/


#ifndef _ICSTASH_LIST_H
#define _ICSTASH_LIST_H

#include "../../ibasecom/IUnknown.h"
#include "../../log/util.h"
#include "./IcstashBase.h"


template<typename T>
interface ICstashList : public IcstashBase
{
public:
    ICstashList(){LogD("ICstashList","=====ICstashList() this: %p\n",this);}
    ICstashList(const ICstashList& l){LogD("ICstashList","====ICstashList拷贝构造  this: %p\n",this);}
    virtual ~ICstashList(){LogD("ICstashList","====~ICstashList()==this: %p\n",this);}
    virtual T getElementAtIndex(int index)const = 0; //取得链表中指定位置的元素值
    virtual ICstashList& push_front(const T& d) = 0;  //前插
    virtual ICstashList& push_back(const T& d) = 0;   //尾插
    virtual ICstashList& insert(const T& d,int pos) = 0; //在任意位置插入
    virtual void removeElementAtIndex(int pos) = 0; //删除链表中指定位置的元素
    virtual int find(const T& d)const = 0; //查找指定数值的元素在链表中出现的位置
    virtual void removeElement(const T& d) = 0; //删除链表中指定的元素
    virtual void updateElementAtIndex(int pos,const T& d) = 0; //更新指定位置的元素
    virtual const T& front()const = 0; //取得链表头节点数据
    virtual const T& back()const = 0;  //取得链表尾节点数据
    virtual void reverse() = 0; //将链表中的元素倒置
};

extern "C"
{
    const IID IID_ILIST = {0x32bb8322, 0xb41b, 0x11cf,{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
}

#endif


Vector 组件接口文件 Icstashvector.h
/*************************************************************************
    > File Name: Icstashvector.h 
    > Created Time: 2016年08月26日 22时30分03秒 CST
 *************************************************************************/
 
 
#ifndef _ICSTASH_VECTOR_
#define _ICSTASH_VECTOR_
 
#include "../../ibasecom/IUnknown.h"
#include "../../log/util.h"
#include "./IcstashBase.h"
 
 
template<typename T>
interface ICstashVector : public IcstashBase
{
public:
    ICstashVector(){ LogD("ICstashVector","ICstashVector() this : %p\n",this); }
    virtual ~ICstashVector(){ LogD("ICstashVector","~ICstashVector() this: %p\n",this); }
    virtual int pushBackElement(const void* element) = 0;
    virtual ICstashVector<T>& pushBackElement(T element) = 0;
    virtual void removeElementAtIndex(int index) = 0;
    virtual const void* fetchElementAtIndex(int index)const = 0;
    virtual void updateElementAtIndex(int index, const void *element) = 0;
 
};
 
extern "C"
{
    const IID IID_IVECTOR = {0x32bb8320, 0xb41b, 0x11cf,{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
}
 
#endif



Vector组件 头文件 cstashvector.h
/*************************************************************************
    > File Name: cstashvector.h
    > Created Time: 2016年08月26日 22时40分03秒 CST
 ************************************************************************/
 
#ifndef _CSTASH_VECTOR_H
#define _CSTASH_VECTOR_H
 
#include "./Icstashvector.h"
 
 
template<typename T>
class CStashVector : public ICstashVector<T>  
{
private:
    int size;                 // Size of each space
    int quantity;             //Number of storage spaces
    char* storage;   //Dynamically allocated array of bytes
    int next;                 //Next empty space
private:
    ULONG m_cRef;
public:
    static int increment;
    static IUnknown* Create(int capacipy);  
private:
    CStashVector(int size = int(), int quantity = int(), int next = int(),char* ptr = NULL);  
    CStashVector(const CStashVector& stash);
    ~CStashVector();
    CStashVector& operator=(const CStashVector& stash);
private:
    void initialize(int bytesByElement,int quantity);
    void inflate(int increase);
private:
    //IUnknown interface
    virtual LONG QueryInterface(const IID& iid, void** ppv);
    virtual ULONG AddRef();
    virtual ULONG Release();
    //ICstashVector interface
    virtual int pushBackElement(const void* element);
    virtual ICstashVector<T>& pushBackElement(T element);
    virtual void removeElementAtIndex(int index);
    virtual const void* fetchElementAtIndex(int index)const;
    virtual void updateElementAtIndex(int index, const void *element);
    //ICstashBase interface
    virtual void travel()const;
    virtual void clear();
    virtual int count()const;
    virtual bool isEmpty()const;
};
 
 
#endif


链表 头文件 IcstashList.h
/*************************************************************************
   > File Name: IcstashList.h
   > Created Time: 2016年09月12日 22时21分19秒 CST
 *************************************************************************/

#ifndef _CSTASH_LIST_H
#define _CSTASH_LIST_H

#include "./IcstashList.h"

template<typename T>
class CstashList : public ICstashList<T>
{
private:
    struct Node
    {
        T      data;
        Node*  next;
        Node(const T& d=T()):data(d),next(NULL){} //零初始化
        operator T(){ return data; }
    };
    Node* head;//头指针,用来保存头节点的地址
    int len;
private:
    ULONG m_cRef;
private:
    CstashList():head(NULL),len(0),m_cRef(0){LogD("CstashList","=====CstashList() this: %p\n",this);}
    CstashList(const CstashList& l);
    void operator=(const CstashList& l);
    ~CstashList();
public:
    static IUnknown* Create();
private:
    Node*& getptr(int pos); //在链表中找指向指定位置的指针
private:
    //IUnknown interface
    virtual LONG QueryInterface(const IID& iid, void** ppv);
    virtual ULONG AddRef();
    virtual ULONG Release();
    //ICstashBase interface
    virtual void travel()const;
    virtual void clear();
    virtual int count()const;
    virtual bool isEmpty()const;
    //IcstashList interface
    virtual T getElementAtIndex(int index)const;  //取得链表中指定位置的元素值
    virtual ICstashList<T>& push_front(const T& d);  //前插
    virtual ICstashList<T>& push_back(const T& d);   //尾插
    virtual ICstashList<T>& insert(const T& d,int pos); //在任意位置插入
    virtual void removeElementAtIndex(int pos); //删除链表中指定位置的元素
    virtual int find(const T& d)const; //查找指定数值的元素在链表中出现的位置
    virtual void removeElement(const T& d);   //删除链表中指定的元素
    virtual void updateElementAtIndex(int pos,const T& d); //更新指定位置的元素
    virtual const T& front()const; //取得链表头节点数据
    virtual const T& back()const; //取得链表尾节点数据
    virtual void reverse(); //将链表中的元素倒置
};

#endif


链表实现文件 cstashList.cpp
/*************************************************************************
   > File Name: cstashList.cpp
   > Created Time: 2016年09月12日 23时50分29秒 CST
 *************************************************************************/

#include <stdio.h>
#include <cassert>
#include <string>
#include <string.h>
#include <stdlib.h>
#include "../include/cstashList.h"
#include "../../log/util.h"

#define TAG "CstashList"

template<typename T>
CstashList<T>::CstashList(const CstashList<T>& l)
{
    len = l.len;
    Node* items[len];
    for(int i=0;i<len;i++)
    {
        items[i] = new Node(l.getElementAtIndex(i));
    }
    for(int i=0;i<len-1;i++)
    {
        items[i]->next = items[i+1];
    }
    head = items[0];
}

template<typename T>
void CstashList<T>::operator=(const CstashList<T>& l)
{
    clear();    
    len = l.len;
    Node* items[len];
    for(int i=0;i<len;i++)
    {
        items[i] = new Node(l.getElementAtIndex(i));
    }
    for(int i=0;i<len-1;i++)
    {
        items[i]->next = items[i+1];
    }
    head = items[0];
}

template<typename T>
CstashList<T>::~CstashList()
{
    LogD(TAG,"====~CstashList()==this: %p\n",this);
    clear();
}

//取得链表中指定位置的元素值
template<typename T>
T CstashList<T>::getElementAtIndex(int index)const  
{
    if(index < 0 || index >= len) throw "索引位置越界";
    if(index == 0) return head->data;
    Node* p = head;
    for(int i=1;i<index;i++)
    {
        p = p->next;
    }
    return p->next->data;
}

//前插
template<typename T>
ICstashList<T>& CstashList<T>::push_front(const T& d)
{
    insert(d,0);
    return *this;
}

//后插
template<typename T>
ICstashList<T>& CstashList<T>::push_back(const T& d)
{
    insert(d,len);
    return *this;
}

//获取链表中节点个数
template<typename T>
int CstashList<T>::count()const
{
    return len;
}
    
//在链表中找指向指定位置的指针
template<typename T>
typename CstashList<T>::Node*& CstashList<T>::getptr(int pos)
{
    if(pos < 0 || pos > len) pos = 0;
    if(pos == 0) return head;
    Node* p = head;
    for(int i=1;i<pos;i++)
    {
        p = p->next;
    }
    return p->next;
}

//在任意位置插入节点
template<typename T>
ICstashList<T>& CstashList<T>::insert(const T& d,int pos)
{
    Node*& pn = getptr(pos);
    Node* p = new Node(d);
    p->next = pn;
    pn = p;
    ++len;
    return *this;
}

//遍历
template<typename T>
void CstashList<T>::travel()const
{
    Node* p = head;
    while(p)
    {
        std::cout << *p << ' ';
        p = p->next;
    }
    std::cout << std::endl;
}

//清空链表
template<typename T>
void CstashList<T>::clear()
{
    while(head)
    {
        Node* p = head->next;
        delete head;
        head = p;
    }
    len = 0;
}
    
//删除链表中指定位置的节点
template<typename T>
void CstashList<T>::removeElementAtIndex(int pos)
{
    if(pos < 0 || pos >= len) return;//有效位置为0~len-1
    Node*& pn = getptr(pos);
    Node* p = pn;
    pn = pn->next;
    delete p;
    --len;
}

//查找指定数值的节点在链表中出现的位置
template<typename T>
int CstashList<T>::find(const T& d)const
{
    Node* p = head;
    int pos = 0;
    while(p)
    {
        if(p->data == d)
          return pos;
        else
          p = p->next;
        ++pos;
    }
    return -1;
}
    
//删除链表中指定数值的节点
template<typename T>
void CstashList<T>::removeElement(const T& d)
{
    int pos;
    while((pos = find(d))!= -1)
    {
        removeElementAtIndex(pos);
    }
}

//修改指定位置的节点数据
template<typename T>
void CstashList<T>::updateElementAtIndex(int pos,const T& d)
{
    if(pos < 0 || pos >= len) return;
    getptr(pos)->data = d;
}

//判断链表是否为空
template<typename T>
bool CstashList<T>::isEmpty()const
{
    return head == NULL;
}

//取得链表中第一个节点数据
template<typename T>
const T& CstashList<T>::front()const
{
    if(isEmpty()) throw "空";
    return head->data;
}

//取得链表中最后一个节点数据
template<typename T>
const T& CstashList<T>::back()const
{
    if(isEmpty()) throw "空";
    Node* p = head;
    while(p->next)
    {
        p = p->next;
    }
    return p->data;
}

//将链表中的元素倒置
template<typename T>
void CstashList<T>::reverse()
{
    if(head == NULL) return;
    Node *pre,*cur,*next;
    pre = head;
    cur = head->next;
    while(cur)
    {
        next = cur->next;
        cur->next = pre;
        pre = cur;
        cur = next;
    }
    head->next = NULL;
    head = pre;
}

template<typename T>
LONG CstashList<T>::QueryInterface(const IID& iid, void** ppv)
{
    LogD(TAG,"enter QueryInterface");
    if(iid == IID_ILIST)
    {
        LogD(TAG,"Return Pointer to ICstashList");
        *ppv = static_cast<ICstashList<T>*>(this);
    }
    else if(iid == IID_IBASE)
    {
        LogD(TAG,"Return Pointer to ICstashBase");
        *ppv = static_cast<IcstashBase*>(this);
    }
    else if(iid == IID_COM_IUnknown)
    {
        LogD(TAG,"Return Pointer to IUnknown");
        *ppv = static_cast<IUnknown*>(this);
    }
    else
    {
        LogD(TAG,"Interface is not surpport!");
        *ppv = NULL;
        return E_NOINTERFACE;
    }
    reinterpret_cast<IUnknown*>(*ppv)->AddRef();
    return S_OK;
}

template<typename T>
ULONG CstashList<T>::AddRef()
{
    m_cRef++;
    LogD(TAG,"AddRef,m_cRef: %d\n",m_cRef);
}


template<typename T>
ULONG CstashList<T>::Release()
{
    LogD(TAG,"Release,m_cRef: %d\n",m_cRef);
    if((--m_cRef) == 0)
    {
        delete this;
        return 0;
    }
    return m_cRef;
}

template<typename T>
IUnknown* CstashList<T>::Create()
{
    LogD(TAG,"enter Create");
    IUnknown* pI = static_cast<ICstashList<T>*>(new CstashList<T>());
    pI->AddRef();
    LogD(TAG,"CstashList Created successful");
    return pI;
}

#ifdef __cplusplus
extern "C"
{
#endif

IUnknown* CoCreateInstance(const IID& iid,void** ppv)
{
    LogD(TAG,"enter coCreateInstance  elementBytes: %d\n",sizeof(T));
    //IUnknown* pI = static_cast<ICstashList<T>*>(new CstashList<T>());
    //pI->AddRef();
    IUnknown* pI = CstashList<T>::Create();
    LogD(TAG,"COM OBJECT CstashList Created successful");
    LONG hr = pI->QueryInterface(iid,ppv);
    if(hr == S_OK)
        pI->Release();
    return pI;
}

#ifdef __cplusplus
}
#endif


Vector 实现文件  cstashvector.cpp
/*************************************************************************
    > File Name: cstashvector.cpp
    > Created Time: 2016年08月26日 23时10分05秒 CST
 ************************************************************************/
 
#include <stdio.h>
#include <cassert>
#include <string>
#include <string.h>
#include <stdlib.h>
#include "../include/cstashvector.h"
#include "../../log/util.h"
 
#define TAG "CStashVector"
 
template<typename T>
int CStashVector<T>::increment = 100;
 
template<typename T>
CStashVector<T>::CStashVector(int size, int quantity, int next,char* ptr) :size(size), quantity(quantity),next(next), storage(ptr) ,m_cRef(0)
{
    LogD(TAG,"CStashVector(), this : %p ,  size: %d, quantity: %d\n",this,size,quantity);
    initialize(size,quantity);
    this->storage = new char[size*quantity];
}
 
template<typename T>
CStashVector<T>::CStashVector(const CStashVector& stash)  
{
    LogD(TAG,"CStashVector拷贝构造");
    this->next = stash.next;
    this->quantity = stash.quantity;
    this->size = stash.size;
    this->storage = new char[stash.quantity * stash.size];
 
    memcpy(this->storage, stash.storage, stash.size * stash.next);
}
 
template<typename T>
CStashVector<T>::~CStashVector()
{
    LogD(TAG,"~CStashVector,this: %p,quantity: %d,storage: %p\n",this,this->quantity,this->storage);
    if (this->storage)
    {
        delete[] this->storage;
        this->storage = NULL;
    }
}
 
template<typename T>
CStashVector<T>& CStashVector<T>::operator=(const CStashVector& stash)
{
    LogD(TAG,"enter operator=");
    assert(this!=&stash);
    this->next = stash.next;
    this->quantity = stash.quantity;
    this->size = stash.size;
 
    if (this->storage != NULL)
        delete[] this->storage;
    this->storage = new char[stash.quantity * stash.size];
 
    memcpy(this->storage, stash.storage, stash.size * stash.next);
    return *this;
}
 
template<typename T>
void CStashVector<T>::initialize(int bytesByElement,int quantity)
{
    this->size = bytesByElement;
    this->quantity = quantity;
    this->next = 0;
    this->storage = NULL;
}
 
template<typename T>
void CStashVector<T>::inflate(int increase)
{
    assert(increase > 0);
    assert(this->storage != NULL);
    int newQuantity = this->quantity + increase;
    int newBytes = this->size * newQuantity;
    int oldBytes = this->size * this->next;
    char* b = new char[newBytes];
    memcpy(b, this->storage, oldBytes);
    delete[] (this->storage);
    this->storage = b;
    this->quantity = newQuantity;
}
 
template<typename T>
int CStashVector<T>::count()const
{
    return this->next;
}
 
template<typename T>
bool CStashVector<T>::isEmpty()const
{
    return !(this->next > 0);
}
 
template<typename T>
void CStashVector<T>::clear()
{
    if (this->storage != NULL && this->next > 0)
    {
        LogD(TAG,"clear vector all element");
        //delete[] this->storage;
        //this->storage = NULL;
        memset(this->storage,0,this->size * this->next);
        this->next = 0;
    }
}
 
template<typename T>
void CStashVector<T>::travel()const
{
    int i = 0;
    LogD(TAG,"======travel begin======");
    while (i < this->next)
    {
        std::cout << *((T*) (this->storage + (i++) * this->size)) << ' ';
    }
    printf("\n");
    LogD(TAG,"===travel end========");
}
 
template<typename T>
int CStashVector<T>::pushBackElement(const void *element)
{
    if (this->next >= this->quantity)
        inflate(increment);
    int starBytes = this->next * this->size;
    memcpy(this->storage+starBytes,element,this->size);
    this->next++;
    return (this->next - 1);
}
 
template<typename T>
ICstashVector<T>& CStashVector<T>::pushBackElement(T element)
{
    if (this->next >= this->quantity)
        inflate(increment);
    int starBytes = this->next * this->size;
    memcpy(this->storage+starBytes,&element,this->size);
    this->next++;
    return *this;
}
 
template<typename T>
void CStashVector<T>::removeElementAtIndex(int index)
{
    LogD(TAG,"=====before  remove=====count: %d, index: %d\n",next,index);
    assert(this->next >= 1 && index <= this->next - 1);
    memcpy(this->storage + index * this->size,
            this->storage + (index + 1) * this->size,
            (this->next - index - 1) * this->size);
    this->next--;
    LogD(TAG,"=====after  remove=====count: %d, index: %d\n",next,index);
}
 
template<typename T>
void CStashVector<T>::updateElementAtIndex(int index, const void *element)
{
    assert(this->next >= 1 && index <= this->next - 1);
    memcpy(this->storage + index * this->size, element, this->size);
}
 
template<typename T>
const void* CStashVector<T>::fetchElementAtIndex(int index)const
{
    assert(index >= 0);
    if (index >= this->next)
        return NULL;
    return this->storage+index * this->size;
}
 
template<typename T>
LONG CStashVector<T>::QueryInterface(const IID& iid, void** ppv)
{
    LogD(TAG,"enter QueryInterface");
    if(iid == IID_IVECTOR)
    {
        LogD(TAG,"Return Pointer to ICstashVector");
        *ppv = static_cast<ICstashVector<T>*>(this);
    }
    else if(iid == IID_IBASE)
    {
        LogD(TAG,"Return Pointer to ICstashBase");
        *ppv = static_cast<IcstashBase*>(this);
    }
    else if(iid == IID_COM_IUnknown)
    {
        LogD(TAG,"Return Pointer to IUnknown");
        *ppv = static_cast<IUnknown*>(this);
    }
    else
    {
        LogD(TAG,"Interface is not surpport!");
        *ppv = NULL;
        return E_NOINTERFACE;
    }
    reinterpret_cast<IUnknown*>(*ppv)->AddRef();
                    
    return S_OK;
}
 
template<typename T>
ULONG CStashVector<T>::AddRef()
{
    m_cRef++;
    LogD(TAG,"AddRef,m_cRef: %d\n",m_cRef);
}
 
template<typename T>
ULONG CStashVector<T>::Release()
{
    LogD(TAG,"Release,m_cRef: %d\n",m_cRef);
    if((--m_cRef) == 0)
    {
        delete this;
        return 0;
    }
    return m_cRef;
}
 
template<typename T>
IUnknown* CStashVector<T>::Create(int capacipy)
{
    LogD(TAG,"enter Create");
    IUnknown* pI = static_cast<ICstashVector<T>*>(new CStashVector<T>(sizeof(T),capacipy));
    pI->AddRef();
    LogD(TAG,"CStashVector Created successful");
    return pI;
}
 
#ifdef __cplusplus
extern "C"  
{
#endif
    IUnknown* CoCreateInstance(const IID& iid,void** ppv)
    {
        LogD(TAG,"enter coCreateInstance");
        //IUnknown* pI = static_cast<ICstashVector<T>*>(new CStashVector<T>(sizeof(T),CAPACIPY));
        //pI->AddRef();
        //LogD(TAG,"COM OBJECT CStashVector Created successful");
        IUnknown* pI = CStashVector<T>::Create(CAPACIPY);
        LONG hr = pI->QueryInterface(iid,ppv);
        if(hr == S_OK)
            pI->Release();
        return pI;
    }
#ifdef __cplusplus
}
#endif


类厂抽象接口 IClassFactory.h
/*************************************************************************
    > File Name: IClassFactory.h
    > Created Time: 2016年08月26日 23时50分23秒 CST
 ************************************************************************/
 
#ifndef _ICLSS_FACTORY_H
#define _ICLSS_FACTORY_H
 
#include "IUnknown.h"
 
 
interface IClassFactory : public IUnknown
{
public:
    IClassFactory(){LogD("IClassFactory: ","IClassFactory()");}
    virtual ~IClassFactory(){LogD("IClassFactory: ","~IClassFactory()");}
    virtual IUnknown* CreateInstance(const IID& iid,void**ppv) = 0;
};
 
 
extern "C"
{
    const CLSID CLSID_LIST_FACTORY = {0x32bb8326, 0xb41b, 0x11cf,{0xa6, 0xbb, 0x0d, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
    const CLSID CLSID_IVECTORFACTORY = {0x32bb8325, 0xb41b, 0x11cf,{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
    const IID IID_ICLSFACTORY = {0x32bb8323, 0xb41b, 0x11cf,{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
    const IID IID_CLS_IUnknown = {0x32bb8328, 0xb41b, 0x11cf,{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
}
 
#endif


 IUnknown.h接口
/*************************************************************************
    > File Name: IUnknown.h  
    > Created Time: 2016年08月27日 17时58分36秒 CST
 ************************************************************************/
 
 
#ifndef IUNKNOWN_H
#define IUNKNOWN_H
 
#include "../log/util.h"
#include "type.h"
 
interface IUnknown
{
public:
    IUnknown(){ LogD("IUnknown","IUnknown()  this: %p\n",this); }
    virtual ~IUnknown(){ LogD("IUnknown","~IUnknown()  this: %p\n",this); }
    virtual LONG  QueryInterface(const IID& iid, void** ppv) = 0;
    virtual ULONG AddRef() = 0;
    virtual ULONG Release() = 0;
};
 
#endif


类型定义文件 type.h
/*************************************************************************
    > File Name: type.h  
    > Created Time: 2016年08月27日 10时58分36秒 CST
 ************************************************************************/
 
 
#ifndef TYPE_H
#define TYPE_H
 
typedef long            LONG;
typedef unsigned long   ULONG;
 
typedef struct _GUID
{
    unsigned long Data1;
    unsigned short Data2;
    unsigned short Data3;
    unsigned char Data4[8];
}GUID;
 
typedef GUID IID;
typedef GUID CLSID;
 
#define interface class
 
#define E_NOINTERFACE -1
#define S_OK  0
 
#endif


Log 文件 util.cpp
/*************************************************************************
    > File Name: util.cpp
    > Created Time: 2016年08月27日 10时58分36秒 CST
 ************************************************************************/
 
#include <string.h>
#include "util.h"
 
using namespace std;
 
bool operator==(const IID& guid1, const IID& guid2)
{
    if(guid1.Data1 != guid2.Data1)
        return false;
    if(guid1.Data2 != guid2.Data2)
        return false;
    if(guid1.Data3 != guid2.Data3)
        return false;
 
    for(int i = 0; i < 8; i++)
    {
        if(guid1.Data4[i] != guid2.Data4[i])
            return false;
    }
    return true;
}
 
void LogD(const char* TAG,const char* format, ...)
{
    if(format !=NULL)
    {
        if(strchr(format,'%'))
        {
            va_list ap;
            va_start(ap,format);
 
            if(strcmp(TAG,"") == 0)
            {
                cout << "";
            }
            else
            {
                printf("%s: ",TAG);
            }
            vprintf(format,ap);
            va_end(ap);
        }
        else
        {
            if(strcmp(TAG,"") == 0)
            {
                cout << "\n";
            }
            else
            {
                cout << TAG << " : " << format << endl;
            }
        }
    }
    else
    {
        cout << TAG << endl;
    }
}
 
void LogE(const char* TAG,const char* format, ...)
{
    if(format != NULL)
    {
        if(strchr(format,'%'))
        {
            va_list ap;
            va_start(ap,format);
            if(strcmp(TAG,"") == 0)
            {
                cout << "";
            }
            else
            {
                fprintf(stderr,"%s: ",TAG);
            }
            vfprintf(stderr,format,ap);
            va_end(ap);
        }
        else
        {
        //    fprintf(stderr,"%s : msg: %s\n",TAG,format);
            if(strcmp(TAG,"") == 0)
            {
                cout << "\n";
            }
            else
            {
                cerr << TAG << " : " << format << endl;
            }
        }
    }
    else
    {
        cout << TAG << endl;
    }
}


客户端

ListClient.h
/*************************************************************************
   > File Name: ListClient.h  
   > Created Time: 2016年09月13日 00时01分30秒 CST
 ************************************************************************/
#ifndef LIST_CLIENT_H
#define LIST_CLIENT_H
 
 
#include <stdlib.h>
#include <dlfcn.h>
#include <unistd.h>
#include "../../ibasecom/IUnknown.h"
#include "../../ibasecom/IClassFactory.h"
#include "../../log/util.h"
#include "../../comPonent/include/IcstashList.h"
 
#define TAG2 "ListClient"
 
typedef IUnknown* (*CoCreateInstance)(const IID& iid,void** ppv);
extern CoCreateInstance g_CoCreate;
 
class ListClient
{
private:
    void* pHandle;
public:
    ListClient(const char* libname)
    {
        LogD(TAG2,"ListClient() Constructor");
        pHandle = dlopen(libname ,RTLD_LAZY);
        if(!pHandle)
        {
            LogE(TAG2,"Load lib %s Exception: %s\n",libname,dlerror());
            exit(EXIT_FAILURE);
        }
        LogD(TAG2,"dlopen lib %s successful, handle: %p\n",libname,pHandle);
        dlerror();
    }
    ~ListClient()
    {
        LogD(TAG2,"======~ListClient()====close library===pHandle: %p\n",pHandle);
        if(pHandle)
            dlclose(pHandle);
        pHandle = NULL;
    }
private:
    ListClient(const ListClient& v);
    ListClient& operator=(const ListClient& v);
public:
    IClassFactory* CreateClsFactory(const CLSID& clsid,const IID& iid)
    {
        IUnknown* (*clsCreate)(const CLSID &clsid, const IID &iid, void **ppv) = NULL;
        char* error = NULL;
        *(void**)(&clsCreate) = dlsym(pHandle, "DllGetClassObject");
        if ((error = dlerror()) != NULL)
        {
            LogE(TAG2,"dlsym find DllGetClassObject Exception: %s\n",error);  
            return NULL;
        }
        LogD(TAG2,"dlsym find DllGetClassObject successful");
        IClassFactory* pClsFactory = NULL;
        IUnknown* pUnknown = (*clsCreate)(clsid,iid,(void**)&pClsFactory);
        if(!pUnknown) return NULL;
        if(pClsFactory == NULL)
        {
            LogE(TAG2,"QueryInterface IClassFactory failed!");
            //创建类厂对象时,查询类厂接口失败,再次查询一次
            LONG hr = pUnknown->QueryInterface(iid,(void**)&pClsFactory);
            if(hr == E_NOINTERFACE)
            {
                pUnknown->Release();
                return NULL;
            }
            else if(hr == S_OK)
                pUnknown->Release();
        }
        LogD(TAG2,"Get an List IClassFactory Pointer successful");
        return pClsFactory;
    }
    template<typename T>
    void CreateComInstance(IClassFactory* pClsFactory,const IID& iid,ICstashList<T>** pList)
    {
        char* error = NULL;
        *(void**)(&g_CoCreate) = dlsym(pHandle,"CoCreateInstance");
        if ((error = dlerror()) != NULL)
        {
            LogE(TAG2,"dlsym find CoCreateInstance Exception: %s\n",error);
            return;
        }
        LogD(TAG2,"dlsym find CoCreateInstance successful");
        IUnknown* pListUnknown = pClsFactory->CreateInstance(iid,(void**)pList);
        if(*pList == NULL)
        {
            //创建Com对象时,查询Com对象接口失败,再次查询一次
            LONG hr = pListUnknown->QueryInterface(iid,(void**)pList);
            if(hr == E_NOINTERFACE)
            {
                pListUnknown->Release();
                return;
            }
            else if(hr == S_OK)
                pListUnknown->Release();
        }
        LogD(TAG2,"Created List COMCompent successful");
    }
    template<typename T>
    ListClient& removeElementAtIndex(ICstashList<T>* pList,int index)
    {
        pList->removeElementAtIndex(index);
        return *this;
    }
    template<typename T>
    ListClient& removeElement(ICstashList<T>*& pList,const T& d)
    {
        pList->removeElement(d);
        return *this;
    }
    template<typename T>
    ListClient& updateElementAtIndex(ICstashList<T>*& pList,int index,const T& d)
    {
        pList->updateElementAtIndex(index,d);
        return *this;
    }
    template<typename T>
    T getElementAtIndex(ICstashList<T>*& pList,int index)const
    {
        return pList->getElementAtIndex(index);
    }
    template<typename T>
    ListClient& push_front(ICstashList<T>*& pList,const T& d)
    {
        pList->push_front(d);
        return *this;
    }
    template<typename T>
    ListClient& push_back(ICstashList<T>*& pList,const T& d)
    {
        pList->push_back(d);
        return *this;
    }
    template<typename T>
    ListClient& insert(ICstashList<T>*& pList,int index,const T& d)
    {
        pList->insert(d,index);
        return *this;
    }
    template<typename T>
    int find(ICstashList<T>*& pList,const T& d)const
    {
        return pList->find(d);
    }
    template<typename T>
    const T& front(ICstashList<T>*& pList)const
    {
        return pList->front();
    }
    template<typename T>
    const T& back(ICstashList<T>*& pList)const
    {
        return pList->back();
    }
    template<typename T>
    void travel(ICstashList<T>*& pList)const
    {
        pList->travel();
    }
    template<typename T>
    void clear(ICstashList<T>*& pList)
    {
        pList->clear();
    }
    template<typename T>
    int count(ICstashList<T>*& pList)const
    {
        return pList->count();
    }
    template<typename T>
    bool isEmpty(ICstashList<T>*& pList)const
    {
        return pList->isEmpty();
    }
    template<typename T>
    void reverse(ICstashList<T>*& pList)
    {
        pList->reverse();
    }
 
};
 
#endif


VectorClient.h
/*************************************************************************
   > File Name: VectorClient.h
   > Created Time: 2016年09月01日 22时01分30秒 CST
 ************************************************************************/
#ifndef VECTOR_CLIENT_H
#define VECTOR_CLIENT_H
 
 
#include <stdlib.h>
#include <dlfcn.h>
#include <unistd.h>
#include "../../ibasecom/IUnknown.h"
#include "../../ibasecom/IClassFactory.h"
#include "../../log/util.h"
#include "../../comPonent/include/Icstashvector.h"
 
#define TAG1 "VectorClient"
 
typedef IUnknown* (*CoCreateInstance)(const IID& iid,void** ppv);
extern CoCreateInstance g_CoCreate;
 
class VectorClient
{
private:
    void* pHandle;
public:
    VectorClient(const char* libname)
    {
        LogD(TAG1,"VectorClient() Constructor");
        pHandle = dlopen(libname ,RTLD_LAZY);
        if(!pHandle)
        {
            LogE(TAG1,"Load lib %s Exception: %s\n",libname,dlerror());
            exit(EXIT_FAILURE);
        }
        LogD(TAG1,"dlopen lib %s successful, handle: %p\n",libname,pHandle);
        dlerror();
    }
    ~VectorClient()
    {
        LogD(TAG1,"======~VectorClient()====close library===pHandle: %p\n",pHandle);
        if(pHandle)
            dlclose(pHandle);
        pHandle = NULL;
    }
private:
    VectorClient(const VectorClient& v);
    VectorClient& operator=(const VectorClient& v);
public:
    IClassFactory* CreateClsFactory(const CLSID& clsid,const IID& iid)
    {
        IUnknown* (*clsCreate)(const CLSID &clsid, const IID &iid, void **ppv) = NULL;
        char* error = NULL;
        *(void**)(&clsCreate) = dlsym(pHandle, "DllGetClassObject");
        if ((error = dlerror()) != NULL)
        {
            LogE(TAG1,"dlsym find DllGetClassObject Exception: %s\n",error);  
            return NULL;
        }
        LogD(TAG1,"dlsym find DllGetClassObject successful");
        IClassFactory* pClsFactory = NULL;
        IUnknown* pUnknown = (*clsCreate)(clsid,iid,(void**)&pClsFactory);
        if(!pUnknown) return NULL;
        if(pClsFactory == NULL)
        {
            LogE(TAG1,"QueryInterface IClassFactory failed!");
            //创建类厂对象时,查询类厂接口失败,再次查询一次
            LONG hr = pUnknown->QueryInterface(iid,(void**)&pClsFactory);
            if(hr == E_NOINTERFACE)
            {
                pUnknown->Release();
                return NULL;
            }
            else if(hr == S_OK)
                pUnknown->Release();
        }
        LogD(TAG1,"Get an Vector IClassFactory Pointer successful");
        return pClsFactory;
    }
    template<typename T>
    void CreateComInstance(IClassFactory* pClsFactory,const IID& iid,ICstashVector<T>** pVector)
    {
        char* error = NULL;
        *(void**)(&g_CoCreate) = dlsym(pHandle,"CoCreateInstance");
        if ((error = dlerror()) != NULL)
        {
            LogE(TAG1,"dlsym find CoCreateInstance Exception: %s\n",error);
            return;
        }
        LogD(TAG1,"dlsym find CoCreateInstance successful");
      //  ICstashVector<T>* pVector = NULL;
        IUnknown* pVectorUnknown = pClsFactory->CreateInstance(iid,(void**)pVector);
        if(*pVector == NULL)
        {
            //创建Com对象时,查询Com对象接口失败,再次查询一次
            LONG hr = pVectorUnknown->QueryInterface(iid,(void**)pVector);
            if(hr == E_NOINTERFACE)
            {
                pVectorUnknown->Release();
                return;
            }
            else if(hr == S_OK)
                pVectorUnknown->Release();
        }
        LogD(TAG1,"Created Vector COMCompent successful");
    }
    template<typename T>
    VectorClient& pushBackElement(ICstashVector<T>*& pVector,const void* element)
    {
        pVector->pushBackElement(element);
        return *this;
    }
    template<typename T>
    VectorClient& pushBackElement(ICstashVector<T>*& pVector,T element)
    {
        pVector->pushBackElement(element);
        return *this;
    }
    template<typename T>
    VectorClient& removeElementAtIndex(ICstashVector<T>* pVector,int index)
    {
        LogD(TAG1,"====before==remove===Vector element count: %d,   index: %d,    size: %d\n",pVector->count(),index,this->count(pVector));
        pVector->removeElementAtIndex(index);
        LogD(TAG1,"====after==remove===Vector element count: %d,   index: %d,  size: %d\n",pVector->count(),index,this->count(pVector));
        return *this;
    }
    template<typename T>
    const void* fetchElementAtIndex(ICstashVector<T>*& pVector,int index)const
    {
        return pVector->fetchElementAtIndex(index);
    }
    template<typename T>
    VectorClient& updateElementAtIndex(ICstashVector<T>*& pVector,int index,const void* element)
    {
        pVector->updateElementAtIndex(index,element);
        return *this;
    }
    template<typename T>
    void travel(ICstashVector<T>*& pVector)const
    {
        pVector->travel();
    }
    template<typename T>
    void clear(ICstashVector<T>*& pVector)
    {
        pVector->clear();
    }
    template<typename T>
    int count(ICstashVector<T>*& pVector)const
    {
        return pVector->count();
    }
    template<typename T>
    bool isEmpty(ICstashVector<T>*& pVector)const
    {
        return pVector->isEmpty();
    }
 
};
 
#endif


clientTest.cpp

/*************************************************************************
   > File Name: clientTest.cpp 
   > Created Time: 2016年08月27日 11时58分36秒 CST
 ************************************************************************/
 
#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "./VectorClient.h"
#include "./ListClient.h"
 
#define TAG "ClientTest"
 
 
void testVector(const char* libnamepath)
{
       int i;
    //测试double类型数据
    /*
    const T bufsize = 8.8;
    T num1 = -20.3,num2 = -12.15,num3 = -30.67,num4 = 5.09;
    T data1 = 9.02,data2 = -3.89;
    T data3 = -100.0,data4 = 6.13;
    */
 
    //测试int类型数据
    
    const T bufsize = 8;
    T num1 = -20,num2 = -12,num3 = -30,num4 = 5;
    T data1 = 9,data2 = -3;
    T data3 = -100,data4 = 6;
    
    /Vector test begin/
    VectorClient* pVectorClient = new VectorClient(libnamepath);
    IClassFactory* pClsFactory = pVectorClient->CreateClsFactory(CLSID_IVECTORFACTORY,IID_ICLSFACTORY);
    if(!pClsFactory)
    {
        delete pVectorClient;
        exit(EXIT_FAILURE);
    }
 
    ICstashVector<T>* pVector = NULL;
    pVectorClient->CreateComInstance(pClsFactory,IID_IVECTOR,&pVector);
    if(!pVector)
    {
        pClsFactory->Release();
        delete pVectorClient;
        exit(EXIT_FAILURE);
    }
    
    pVectorClient->pushBackElement(pVector,&num1).pushBackElement(pVector,&num2).pushBackElement(pVector,&num3).pushBackElement(pVector,&num4);
 
    pVectorClient->travel(pVector);
 
    for (i = 0; i < pVectorClient->count(pVector); i++)  
    {
        std::cout << "pVector[" << i << "] = " << *(T*) (pVectorClient->fetchElementAtIndex(pVector,i))
                << std::endl;
    }
    LogD(TAG,"Vector元素个数: %d\n",pVectorClient->count(pVector));
    pVectorClient->removeElementAtIndex(pVector,1).removeElementAtIndex(pVector,2);
 
    LogD(TAG,"Vector元素个数==2==: %d\n",pVectorClient->count(pVector));
//    pVectorClient->removeElementAtIndex(pVector,pVectorClient->count(pVector)-1);
 
    pVectorClient->updateElementAtIndex(pVector,pVectorClient->count(pVector) - 1, &bufsize);
 
    LogD(TAG,"======更新后的结果遍历====begin====");
    pVectorClient->travel(pVector);
    LogD(TAG,"======更新后的结果遍历====end======");
 
    for (i = 0; i < pVectorClient->count(pVector); i++)  
    {
        std::cout << "pVector[" << i << "] ="
                << *(T*) (pVectorClient->fetchElementAtIndex(pVector,i)) << std::endl;
    }
 
    pVectorClient->pushBackElement(pVector,data3).pushBackElement(pVector,data4);
    pVectorClient->travel(pVector);
     
    pVectorClient->updateElementAtIndex(pVector,1,&data2).updateElementAtIndex(pVector,pVectorClient->count(pVector) - 1, &data1);
    pVectorClient->travel(pVector);
 
    pVectorClient->clear(pVector);
    bool isEmpty = pVectorClient->isEmpty(pVector);
    LogD(TAG,"isEmpty: %d\n",isEmpty);
    pVectorClient->travel(pVector);
 
    LogD(TAG,"Release the ICstashVector interface");
    pVector->Release();
    pVector = NULL;
 
    LogD(TAG,"free Vector ClassFactory Object");
    pClsFactory->Release();
    pClsFactory = NULL;
 
    delete pVectorClient;
    pVectorClient = NULL;
    Vector test end/
}
 
 
void testList(const char* libnamepath)
{
       int i;
    //测试double类型数据
    /*
    const T bufsize = 8.8;
    T num1 = -20.3,num2 = -12.15,num3 = -30.67,num4 = 5.09;
    T data1 = 9.02,data2 = -3.89;
    T data3 = -100.0,data4 = 6.13;
    */
 
    //测试int类型数据
    
    const T bufsize = 8;
    T num1 = -20,num2 = -12,num3 = -30,num4 = 5;
    T data1 = 9,data2 = -3;
    T data3 = -100,data4 = 6;
    
    /List test begin/
    ListClient* pListClient = new ListClient(libnamepath);
    IClassFactory* pClsFactory = pListClient->CreateClsFactory(CLSID_LIST_FACTORY,IID_ICLSFACTORY);
    if(!pClsFactory)
    {
        delete pListClient;
        exit(EXIT_FAILURE);
    }
 
    ICstashList<T>* pList = NULL;
    pListClient->CreateComInstance(pClsFactory,IID_ILIST,&pList);
    if(!pList)
    {
        pClsFactory->Release();
        delete pListClient;
        exit(EXIT_FAILURE);
    }
 
    pListClient->push_front(pList,num1).push_front(pList,num2).push_front(pList,num3);
    pListClient->travel(pList);
 
    pListClient->insert(pList,2,num4).insert(pList,8,data1);
    pListClient->travel(pList);
 
    pListClient->insert(pList,-10,data2);
    pListClient->travel(pList);
 
    pListClient->insert(pList,2,data3);
    pListClient->travel(pList);
 
    pListClient->push_back(pList,data3).push_back(pList,data4);  
    pListClient->travel(pList);
 
    pListClient->removeElement(pList,data1).removeElement(pList,data3);
    pListClient->travel(pList);
 
    pListClient->updateElementAtIndex(pList,1,num2);
    pListClient->travel(pList);
 
    pListClient->updateElementAtIndex(pList,pListClient->find(pList,num4),data3).removeElement(pList,num2);
    pListClient->travel(pList);
 
    std::cout << TAG << "===倒置前===第一个元素: " << pListClient->getElementAtIndex(pList,0) << std::endl;
 
    pListClient->reverse(pList);
    pListClient->travel(pList);  
    std::cout << TAG << "===倒置后===第一个元素: " << pListClient->getElementAtIndex(pList,0) << std::endl;
 
    while(!pListClient->isEmpty(pList))  
        pListClient->removeElementAtIndex(pList,0);
    LogD(TAG,"=====List 元素个数: %d\n",pListClient->count(pList));
    
    try{
        std::cout << TAG << "===删除后===List中第一个元素: " << pListClient->getElementAtIndex(pList,0) << std::endl;
    }catch(const char* e){
        LogE(TAG,e);
    }catch(...){
        LogE(TAG,"未知错误");
    }
 
 
    pListClient->push_back(pList,num2).push_front(pList,data1).insert(pList,1,num4);
    pListClient->travel(pList);
    pListClient->reverse(pList);
    pListClient->travel(pList);  
 
    pListClient->clear(pList);
    bool isEmpty = pListClient->isEmpty(pList);
    LogD(TAG,"isEmpty: %d\n",isEmpty);
    pListClient->travel(pList);
 
    LogD(TAG,"Release the ICstashList interface");
    pList->Release();
    pList = NULL;
 
    LogD(TAG,"free List ClassFactory Object");
    pClsFactory->Release();
    pClsFactory = NULL;
 
    delete pListClient;
    pListClient = NULL;
    /List test end/
}
 
int main(int argc, char** argv)  
{
    if(strcmp("./bin/client",argv[0]) || argc != 4)
    {
        LogD(TAG,"Usage: %s -l库名1 -l库名2 -L库路径\n",argv[0]);
        exit(EXIT_FAILURE);
    }
    char* error = NULL;
    char* libvector = NULL;
    char* liblist = NULL;
    char* libpath = NULL;
    int libnamepathlen = 0;
    int cmdoption;
    while((cmdoption = getopt(argc,argv,"l:l:L:"))!= -1)
    {
        switch(cmdoption)
        {
            case 'l':
                if(!strcmp(optarg,"libvectorcompent.so")){
                    libvector = optarg;
                }
                else if(!strcmp(optarg,"liblistcompent.so")){
                    liblist = optarg;
                }
                libnamepathlen += strlen(optarg);
                LogD(TAG,"libname: %s,  libnamepathlen: %d\n",optarg,libnamepathlen);
                break;
            case 'L':
                libpath = optarg;
                libnamepathlen += strlen(optarg);
                LogD(TAG,"libpath: %s,  libnamepathlen: %d\n",optarg,libnamepathlen);
                break;
        }
    }
    char libnamepath[libnamepathlen + 1];
    if(libvector)
    {
        memset(libnamepath,0,sizeof(sizeof(libnamepath)));
        memcpy(libnamepath,libpath,strlen(libpath));
        strcat(libnamepath,"/");
        strcat(libnamepath,libvector);
        LogD(TAG,"libname: %s, libpath: %s, libnamepath :%s\n",libvector,libpath,libnamepath);
        LogD(TAG,"======测试Vector开始==========\n");
        testVector(libnamepath);
        LogD(TAG,"======测试Vector结束==========\n");
    }
    if(liblist)
    {
        memset(libnamepath,0,sizeof(sizeof(libnamepath)));
        memcpy(libnamepath,libpath,strlen(libpath));
        strcat(libnamepath,"/");
        strcat(libnamepath,liblist);
        LogD(TAG,"libname: %s, libpath: %s, libnamepath :%s\n",liblist,libpath,libnamepath);
        LogD(TAG,"======测试List开始==========\n");
        testList(libnamepath);
        LogD(TAG,"======测试List结束==========\n");
    }
 
    exit(EXIT_SUCCESS);
}
 
 
makefile 文件
CUR_DIR = $(shell pwd)
 
OBJDIR = $(CUR_DIR)/obj
LIBDIR = $(CUR_DIR)/lib
BINDIR = $(CUR_DIR)/bin
 
LOGDIR = $(CUR_DIR)/log
CLIENTDIR = $(CUR_DIR)/client/src
COMPONENTDIR = $(CUR_DIR)/comPonent/src
CLASSFACTORYDIR = $(CUR_DIR)/classFactory/src
 
 
objects = $(OBJDIR)/*.o $(LIBDIR)/*.so $(BINDIR)/*
 
all : targetdir vectorcompent listcompent
    g++ $(CLIENTDIR)/clientTest.cpp -ldl -lvectorcompent -llistcompent -L$(LIBDIR) -o$(BINDIR)/client
    @echo "===========client  build SUCCESSFULL==================="
 
vectorcompent : $(OBJDIR)/cstashvector.o $(OBJDIR)/VectorClassFactory.o $(OBJDIR)/util.o
    g++ -shared $(OBJDIR)/cstashvector.o $(OBJDIR)/VectorClassFactory.o $(OBJDIR)/util.o -o $(LIBDIR)/libvectorcompent.so
    @echo "===========vector Component build SUCCESSFULL==================="
 
$(OBJDIR)/cstashvector.o : $(COMPONENTDIR)/cstashvector.cpp
    g++ -c -fpic $(COMPONENTDIR)/cstashvector.cpp -o $(OBJDIR)/cstashvector.o
 
$(OBJDIR)/VectorClassFactory.o : $(CLASSFACTORYDIR)/VectorClassFactory.cpp
    g++ -c -fpic $(CLASSFACTORYDIR)/VectorClassFactory.cpp -o $(OBJDIR)/VectorClassFactory.o
 
listcompent : $(OBJDIR)/cstashList.o $(OBJDIR)/ListClassFactory.o $(OBJDIR)/util.o
    g++ -shared $(OBJDIR)/cstashList.o $(OBJDIR)/ListClassFactory.o $(OBJDIR)/util.o -o $(LIBDIR)/liblistcompent.so
    @echo "===========list Component build SUCCESSFULL==================="
 
$(OBJDIR)/cstashList.o : $(COMPONENTDIR)/cstashList.cpp
    g++ -c -fpic $(COMPONENTDIR)/cstashList.cpp -o $(OBJDIR)/cstashList.o
 
$(OBJDIR)/ListClassFactory.o : $(CLASSFACTORYDIR)/ListClassFactory.cpp
    g++ -c -fpic $(CLASSFACTORYDIR)/ListClassFactory.cpp -o $(OBJDIR)/ListClassFactory.o
 
$(OBJDIR)/util.o : $(LOGDIR)/util.cpp
    g++ -c -fpic $(LOGDIR)/util.cpp -o $(OBJDIR)/util.o
 
 
targetdir :  
    @rm -rf $(OBJDIR) $(LIBDIR) $(BINDIR)
    @mkdir $(OBJDIR) $(LIBDIR) $(BINDIR)
 
.Python : clean
clean :  
    @rm -f ${objects}
    @clear



注意事项:

编译运行,按如下操作

1 ~/.bashrc 中,在该文件的未尾,可采用如下语句来使设置生效:

       export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.

2 make clean

   make

3 执行

   ./bin/client -llibvectorcompent.so -lliblistcompent.so -L./lib


具体代码下载
https://code.csdn.net/u011641755/linux_com/tree/master

好了,欢迎广大技术开发者提出宝贵的意见和指导




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值