在Linux下实现COM组件(转载)

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

本文由导学宝转自:http://blog.csdn.net/chenspnjupt1234/article/details/5923672

好久没有写代码啦,今天翻到大学时候写的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!


新学期领福利!购实物周边送年卡会员! T恤、键盘、双肩包等周边任选!还能解锁资源下载、VIP文章等多重会员权益! 阅读详情

相关推荐

LinuxCom组件例子

Linux 下C++ Com组件demo

com学习记录()——在Linux环境下完成com组件编程分离服务端(动态库)客户端(可执行程序)

Linux下没有unknwn.h系统头文件,所以在Linux环境编写com组件时应该自己定义这个类和接口 此项目分为两个文件夹,分别是服务端(生成动态库)和客户端(可执行文件) 文件结构 同级目录下两个文件夹,一个lib文件夹用于服务端动态库生成,一个client文件夹用于客户端测试编写程序 **/com ************/lib ************************************base.h ************************************IUnk

hhl_work的博客 1369

Linux实现COM组件(原创)

<br />好久没有写代码啦,今天翻到大学时候写的COM组件,当时那个叫崇拜COM技术啊。不过发现,工作中根本没啥用处。反正没事干,想想把COM组件Linux环境下,实现一下。<br />COM组件是一种编程规范,它规定了软件编程的一般方法,虽然它由Microsoft公司制定和提出,但是它的规则也可以在Linux下使用,下面是在Linux实现COM组件的方法。<br />----参考《COM技术内幕》一书。<br />COM实现的技术,主要是C++的虚函数、多继承以及动态链接库(DLL)技术。<br /

chenspnjupt1234的专栏 5812

linuxcom技术,《com 技术内幕》

com 技术内幕》第1章 组件1、COM,即组件对象模型,是关于如何建立组件以及如何通过组件建构应用程序的一个规范。2、组件的优点:应用程序可随时间的流逝而发展变化;定制应用程序;组件库;分布式组件。3、对组件的需求:组件必须动态连接;必须隐藏其内部实现细节。4、COM组件是以Win32动态链接库(DLLs)或可执行文件(EXEs)的形式发布的可执行代码组成的。遵循COM规范编写的组件将能够满足...

weixin_36044132的博客 1237

操作系统COM组件的概念

本文简单介绍操作系统COM组件的概念。 COM组件 1.1. 基本概念 1.1.1. 来源 COM component(COM组件)是微软公司为了计算机工业的软件生产更加符合人类的行为方式开发的一种新的软件开发技术。在COM构架下,人们可以开发出各种各样的功能专一的组件,然后将它们按照需要组合起来,构成复杂的应用系统。由此带来的好处是多方面的:可以将系统中的组件用新的替换掉,以便随时进行系统的升级和定制;可以在多个应用系统中重复利用同一个组件;可以方便的将应用系统扩展到网络环境下;COM与语言,平台无关的

weixin_41883890的博客 2135

linux python 查看所有com资源

Linux Python 查看所有 COM 资源 在现代计算环境中,COMComponent Object Model)是一种重要的技术,它允许不同的软件组件进行互操作。在Linux系统中,虽然COM并不是原生支持的技术,但我们仍然有办法查找设备的COM端口,尤其是通过Python编程来实现。本文将介绍如何在Linux...

weixin_31125161的博客 315

推荐几款COM组件开发的入门书籍

推荐几本个人读过的比较不错的COM组件相关的书籍,按我的阅读感受排名如下: 1,《Visual C++实践与提高-COMCOM+篇》         这本书我放在第一位,倒不是它有多么出色,但我却认为它是最适合新手的。它的内容基本都是抄袭下面潘爱民那本《COM原理与应用》的,但我推荐它有两点原因,首先,基本照搬潘那本书的原理性的东西,但加入了许多实例,比前者纯理论

在线笔记 1609

[转载]COM技术纵横谈

一:概述 PC机自从诞生以来,硬件经历了无数变化,CPU从最初的INTEL 8086到现在PIII满大街都是也只不过十几年。微软的WINDOWS操作系统从最初的1.0版本到现在即将推出WIN2000,一直是桌面系统上装机量最大的OS。 作为软件开发人员,使用着包括Visual Basic,Visual C++,Delphi包括最新的Borland C++ builder等等在内的众多开发环境为...

weixin_33887443的博客 112

XPCOMLINUX下的组件开发技术

(2012-10-15 16:36:21) 转载▼ 标签:  mozilla浏览器   组件   头文件   库文件   字符串   杂谈   COM技术作为微软推行的一种组件技术,在WINDOWS平台站有重要地位,在模块重用,跨语言通信等方面都能见到其身影。但今天给我要介绍的是LINUX

Jingle的专栏 2531

COM技术纵横之谈(初学者)

C O M 技术纵横谈 一(转载) 一:概述 PC机自从诞生以来,硬件经历了无数变化,CPU从最初的INTEL 8086到 现在PIII满大街都是也只不过十几年。微软的WINDOWS操作系统从最初的 1.0版本到现在即将推出WIN2000,

zqf5816的专栏 678

linux 存储栈图片转载

转载图片,方便后续查看

qq_33152179的博客 93

使用现有的COM

使用现有的COM #include "ClassDll.h"#include "ClassDll_i.c"if ( FAILED( CoInitialize(NULL) )){return;}IClass* pIClass;hr = CoCreateInstance(CLSID_Class,NULL,CLSCTX_INPROC_SERVER,I...

weixin_30292843的博客 104

Linux下Mongodb安装和启动配置 转载

原文地址:https://www.cnblogs.com/Jimmy104/p/6181899.html 以下文章为转载,感谢网友,原文链接 http://blog.csdn.net/yuwenruli/article/details/8529192 1.下载安装包 wget http://fastdl.mongodb.org/linux/mongodb-linux-i686-...

weixin_34203426的博客 126

Linux实现删除撤回的方法。

RM命令改造 vim /etc/bashrc 在文件的最前端添加如下代码 #修改rm命令 alias rm=delete #命令别名,通过delete来实现rm改为mv alias r=delete alias rl='ls /trash' #rl 命令显示回收站中的文件 alias ur=undelfile #ur 命令找回回收站的文件 undelfile() {...

weixin_33834075的博客 8764

Windows下虚拟串口工具:com0com可做串口调试用

http://sourceforge.net/projects/com0com/ The Null-modem emulator (com0com) is a kernel-mode virtual serial port driver for Windows. You can create an unlimited number of virtual COM port pairs a...

bangrulu3140的博客 507

通过COM口管理Linux系统服务器简介

下面已dell2950服务器为例说明怎么通过com口管理linux服务器一:配置BIOS实现通过com启用控制台重定向1,开机过程按F2进入BIOS设置菜单2,进入Serial Communication菜单3,设置Serial...

congsikuai0611的博客 514

linux用文件锁实现保证一个程序只能启动一个进程

转载自:   #include stdio.h> #include unistd.h> #include fcntl.h> #include errno.h> int main(int argc,char* argv[]) {  int fd;  int lock_result;  struct flock lock;  char * pFileName = "tmp

三言两语 2382
上一篇: 项目规划管理 - 7 (全文完)
下一篇: gcc的-D和-U参数
daoxuebao_com
博客等级 码龄15年 5粉丝 5原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值