com学习记录(三)——在Linux环境下完成com组件编程

14 篇文章 1 订阅

com学习记录(一)——基本概念
com学习记录(二)——使用vs2019完成windows下的com组件编程
com学习记录(三)——在Linux环境下完成com组件编程
com学习记录(四)——在Linux环境下完成com组件编程分离服务端(动态库)客户端(可执行程序)

​ Linux系统并没有对应的注册表和IUnknow接口,所以需要自己编写。

  • 类型定义 type.h

    /*
    	$file:		type.h
    	$date:		2020年8月13日
    	$author:	hehl
    	$describe:	类型定义
    	$other:
    */
    #ifndef __TYPE_H__
    #define __TYPE_H__
    
    typedef long HRESULT;			// 32位机为四字节,64位机为八字节,和指针的类型长度一致
    typedef unsigned long ULONG;
    
    typedef struct _GUID
    {
    	unsigned long Data1;		// 32位 0x0000-0x0000
    	unsigned short Data2;		// 16位 0x0000
    	unsigned short Data3;		// 16位 0x0000
    	unsigned char Data4[8];		// 64位	0x0000-0x0000-0x0000-0x0000
    }GUID;	// guid	128位的全局唯一标识符(Globally Unique Identifier)
    
    typedef GUID IID;
    
    #define interface struct	// 定义接口为结构体
    
    #define E_NOINTERFACE 0x80004002L	// 错误码,先不管他
    #define S_OK 0
    
    #endif
    
  • 接口基类 iunknown.h

/*
	$file:		iunknown.h
	$date:		2020年8月13日
	$author:	hehl
	$describe:	接口基类
	$other:
*/
#ifndef __IUNKNOWN_H__
#define __IUNKNOWN_H__

#include "type.h"

interface IUnknown	// interface相当于struct,c语言风格
{
	virtual HRESULT QueryInterface(const IID& iid, void** ppv) = 0;	// 请求接口指针,相当于查询一个方法
	virtual ULONG AddRef() = 0;		// 增加引用计数
	virtual ULONG Release() = 0;	// 减少引用计数
};	// windows提供的IUnknown类的三个接口,Linux下需要自己实现,windows这里为类

#endif
  • GUID和接口头文件 interface.h
/*
	$file:		interface.h
	$date:		2020年8月13日
	$author:	hehl
	$describe:	接口类 + GUID
	$other:
*/
#ifndef __INTERFACE_H__
#define __INTERFACE_H__

#include "iunknown.h"

interface IX : IUnknown		// 这个总感觉怪怪的,先不管这种写法了,按照c++的写法应该是继承把?
{
	virtual void Fx() = 0;	// 纯虚函数,由派生类实现具体方法
};

interface IY : IUnknown
{
	virtual void Fy() = 0;	// 纯虚函数,由派生类实现具体方法
};

interface IZ : IUnknown
{
	virtual void Fz() = 0;	// 纯虚函数,由派生类实现具体方法
};

// 8 4 4 12
// 9F153BC9-E06F-7B23-F4FC-A96B64ABA9D3
extern "C"
{
	const IID IID_IX = { 0x9F153BC9, 0xE06F , 0x7B23 , \
		{0xF4, 0xFC, 0xA9, 0x6B, 0x64, 0xAB, 0xA9, 0xD3} };
	const IID IID_IY = { 0x9F153BC9, 0xE06F , 0x7B23 , \
		{0xF4, 0xFC, 0xA9, 0x6B, 0x64, 0xAB, 0xA9, 0xD4} };
	const IID IID_IZ = { 0x9F153BC9, 0xE06F , 0x7B23 , \
		{0xF4, 0xFC, 0xA9, 0x6B, 0x64, 0xAB, 0xA9, 0xD5} };
	const IID IID_IUnknown = { 0x9F153BC9, 0xE06F , 0x7B23 , \
		{0xF4, 0xFC, 0xA9, 0x6B, 0x64, 0xAB, 0xA9, 0xD6} };
}

#endif
  • 组件实现文件 component.cpp
/*
	$file:		component.cpp
	$date:		2020年8月13日
	$author:	hehl
	$describe:	组件实现
	$other:
*/
#include <iostream>
#include "type.h"
#include "interface.h"

using namespace std;

bool operator==(const IID& guid1, const IID& guid2)
{
	if (guid1.Data1 != guid2.Data1 || guid1.Data2 != guid2.Data2 || \
		guid1.Data3 != guid2.Data3)
	{
		return false;
	}
	for (int i = 0; i < 8; i++)
	{
		if (guid1.Data4[i] != guid2.Data4[i])
		{
			return false;
		}
	}
	return true;
}

// 额... = =、	类以后还是定义再头文件里面好点~~先不管了
class CA : public IX
{
private:
	// IUnknown的接口
	virtual HRESULT QueryInterface(const IID& iid, void** ppv);
	virtual ULONG AddRef();
	virtual ULONG Release();

	// IX的接口
	virtual void Fx();

public:
	CA();
	~CA();

private:
	long m_cRef;
};

CA::CA()
{
	cout << "CA::CA()\n";
}

CA::~CA()
{
	cout << "CA::~CA()\n";
}

HRESULT CA::QueryInterface(const IID& iid, void** ppv)
{
	if (iid == IID_IX)
	{
		cout << "CA::QueryInterface() to IX\n";
		*ppv = static_cast<IX*>(this);	// 等价于 *ppv = (IX*)this;
	}
	else if (iid == IID_IUnknown)
	{
		cout << "CA::QueryInterface() to IUnknown\n";
		*ppv = static_cast<IUnknown*>(this);
	}
	else
	{
		cout << "CA::QueryInterface() Interface is not support\n";
		*ppv = NULL;
		return E_NOINTERFACE;
	}
	reinterpret_cast<IUnknown*>(*ppv)->AddRef();
}

ULONG CA::AddRef()
{
	m_cRef++;
	cout << "CA::AddRef() m_cRef:" + m_cRef << endl;
}

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

void CA::Fx()
{
	cout << "CA::Fx() called\n";
}

// 由动态库指向此函数
extern "C" IUnknown * CreateInstance()
{
	IUnknown* pI = static_cast<IX*>(new CA);
	pI->AddRef();
	return pI;
}
  • 客户端 client.cpp
/*
	$file:		client.cpp
	$date:		2020年8月13日
	$author:	hehl
	$describe:	组件实现
	$other:
*/
#include <iostream>
#include "interface.h"
#include "create.h"

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

	cout << "Enter the file name of a component to use[lib***.so]:";
	cin >> name;
	cout << "Get an IUnknown pointer." << endl;
	
	IUnknown* pUnknown = create.CallCreateInstance(name);
	if (pUnknown == NULL)
	{
		cout << "CallCreateInstance fail!\n";
		exit(1);
	}
	
	cout << "Get Interface IX.\n";
	IX* pIX = NULL;
	hr = pUnknown->QueryInterface(IID_IX, (void**)&pIX);
	if (hr < 0)
	{
		cout << "Counld not get the IX interface.\n";
	}
	else
	{
		cout << "Success get the IX interface.\n";
		pIX->Fx();
		pIX->Release();
	}
	
	cout << "Release the IUnknown interface.\n";
	pUnknown->Release();
	
	create.closeHandle();
	return 0;

}
  • Makefile
objects=component.o client.o create.o

all : libcmpnt client

libcmpnt:component.o
        g++ -shared -Wl,-soname -O3 -o libcmpnt.so component.o

cmpnt.o : interface.h  iunknown.h  type.h
        g++ -c -fPIC component.cpp  -O3 -o component.o

client : client.o create.o
        g++ -g -rdynamic  -Wl,--no-as-needed -ldl -o client client.o create.o

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

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

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

编译、运行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值