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}
编译、运行