在Linux下实现COM组件(原创)

好久没有写代码啦,今天翻到大学时候写的COM组件,当时那个叫崇拜COM技术啊。不过发现,工作中根本没啥用处。反正没事干,想想把COM组件在Linux环境下,实现一下。

COM组件是一种编程规范,它规定了软件编程的一般方法,虽然它由Microsoft公司制定和提出,但是它的规则也可以在Linux下使用,下面是在Linux下实现COM组件的方法。
----参考《COM技术内幕》一书。
COM实现的技术,主要是C++的虚函数、多继承以及动态链接库(DLL)技术。
COM组件的实现:
--类型定义文件type.h
#ifndef TYPE_H
#define TYPE_H

typedef long            HRESULT;
typedef unsigned long   ULONG;

typedef struct _GUID
{
    unsigned long Data1;
    unsigned short Data2;
    unsigned short Data3;
    unsigned char Data4[8];
} GUID;
typedef GUID IID;

#define interface struct

#define E_NOINTERFACE 0x80004002L
#define S_OK  0

#endif

--GUID定义文件guids.cpp
#include "type.h"

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

        extern const IID IID_IY =
                {0x32bb8321, 0xb41b, 0x11cf,
                {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

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

        extern const IID IID_IUnknown =
                {0x32bb8323, 0xb41b, 0x11cf,
                {0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};
}

--接口基类:IUnknown.h
#ifndef IUNKNOWN_H
#define IUNKNOWN_H

#include "type.h"

interface IUnknown
{
        virtual HRESULT  QueryInterface(const IID& iid, void** ppv)=0;
        virtual ULONG    AddRef()=0;
        virtual ULONG    Release()=0;
};

#endif

--接口定义头文件iface.h
#ifndef IFACE_H
#define IFACE_H

#include "IUnknown.h"

interface IX:IUnknown
{
        virtual void Fx()=0;
};

interface IY:IUnknown
{
        virtual void Fy()=0;
};

interface IZ:IUnknown
{
        virtual void Fz()=0;
};

extern "C"
{
        extern const IID IID_IX;
        extern const IID IID_IY;
        extern const IID IID_IZ;
}

#endif

--组件实现文件cmpnt1.cpp
#include <iostream>
#include "type.h"
#include "iface.h"
#include "guids.cpp"

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 trace1(const char* msg) { cout << "Component1:/t" << msg << endl; }

class CA:public IX
{
private:
        //IUnknown interface
        virtual HRESULT QueryInterface(const IID& iid, void** ppv);
        virtual ULONG   AddRef();
        virtual ULONG   Release();

        //IX interface
        virtual void Fx() { cout << "FX" << endl; }

public:
        //Constructor
        CA():m_cRef(0){}

        //Destructor
        ~CA(){ trace1("CA Destoryed by itself!"); }

private:
        long m_cRef;
};

HRESULT CA::QueryInterface(const IID& iid, void** ppv)
{

        if(iid == IID_IX)
        {
                trace1("Return Pointer to IX");
                *ppv = static_cast<IX*>(this);
        }
        else if(iid == IID_IUnknown)
        {
                trace1("Return Pointer to IUnknown");
                *ppv = static_cast<IUnknown*>(this);
        }
        else
        {
                trace1("Interface is not surpport!");
                *ppv = NULL;
                return E_NOINTERFACE;
        }
        reinterpret_cast<IUnknown*>(*ppv)->AddRef();

        return S_OK;
}

ULONG CA::AddRef()
{
        m_cRef++;
}

ULONG CA::Release()
{
        if((--m_cRef) == 0)
        {
                delete this;
                return 0;
        }
        return m_cRef;
}

extern "C" IUnknown* CreateInstance()
{
        IUnknown* pI = static_cast<IX*>(new CA);
        pI->AddRef();
        return pI;
}

客户端的实现:
--create.h
#ifndef CREATE_H
#define CREATE_H

#include <iostream>
#include "IUnknown.h"
#include <dlfcn.h>

using namespace std;

struct CREATE
{
        void* handle;
        IUnknown* CallCreateInstance(char *name);
        void closeHandle();
};

#endif

--创建组件create.cpp
#include "create.h"

typedef IUnknown* (*CREATEFUNCPTR)();

IUnknown* CREATE::CallCreateInstance(char* name)
{
        CREATEFUNCPTR   CreateInstance;
        char*           error;
        IUnknown*       pUnknown;

        handle = dlopen(name , RTLD_LAZY);

        if(!handle)
        {
                cout << "Load lib " << name << " fail!" << endl;
                exit(1);
        }

        dlerror();
        *(void**)(&CreateInstance) = dlsym(handle, "CreateInstance");
        if ((error = dlerror()) != NULL)
        {
                cout << error << endl;
                exit(1);
        }

        pUnknown = CreateInstance();

//      dlclose(handle);
        return pUnknown;
}

void   CREATE::closeHandle()
{
        dlclose(handle);
}

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;
}

--客户端实现client1.cpp
#include <iostream>
#include "iface.h"
#include "create.h"
#include "guids.cpp"

void trace(const char* msg) { cout << "Client1:/t" << msg << endl; }

int main(int argc, char** argv)
{
        HRESULT hr;
        char name[40];
        CREATE  create;

        cout << "Enter the file name of a component to use[lib***.so]:";
        cin >> name;
        cout << endl;

        trace("Get an IUnknown pointer.");
        IUnknown* pUnknown = create.CallCreateInstance(name);
        if(pUnknown == NULL)
        {
                trace("CallCreateInstance fail!");
                exit(1);
        }

        trace("Get Interface IX.");

        IX* pIX = NULL;

        hr = pUnknown->QueryInterface(IID_IX, (void**)&pIX);

        if(hr >= 0)
        {
                trace("Success get the IX.");
                pIX->Fx();
                pIX->Release();
        }
        else
        {
                trace("Counld not get the IX interface.");
 }
        trace("Release the IUnknown interface.");
        pUnknown->Release();

        create.closeHandle();
        return 0;
}

--Makefile
objects=cmpnt1.o client1.o create.o

all : libcmpnt1 client1

libcmpnt1 : cmpnt1.o
        g++ -shared -W1,-soname -O3 -o libcmpnt1.so cmpnt1.o

cmpnt1.o : guids.cpp iface.h  IUnknown.h  type.h
        g++ -c -fPIC cmpnt1.cpp  -O3 -o cmpnt1.o

client1 : client1.o create.o
        g++ -g -rdynamic -ldl -o client1 client1.o create.o

client1.o :
        g++ -g -c client1.cpp

create.o :
        g++ -g -c create.cpp

.PYTHON : clean
clean :
        rm -f ${objects}

运行时注意:需要保证当前的环境下环境变量LD_LIBRARY_PATH已经设置。
具体运行方法如下:
[root@localhost cust_comp]# export LD_LIBRARY_PATH=.
[root@localhost cust_comp]# ./client1
Enter the file name of a component to use[lib***.so]:libcmpnt1.so

Client1:        Get an IUnknown pointer.
Client1:        Get Interface IX.
Component1:     Return Pointer to IX
Client1:        Success get the IX.
FX
Client1:        Release the IUnknown interface.
Component1:     CA Destoryed by itself!

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值