插件规范
COM组件为了联合开发实现统一标准
统一虚表标准
1.虚表函数数量:不要有虚析构
2.虚表函数顺序:不要使用虚函数重载
3.虚表数量:不能用多重继承(两个基类都有虚函数), 不能使用虚继承
TLB com ==> 统一接口的二进制标准
Int有的语言是两个字节,有的是四个字节。像这种模糊的类型定义都去掉了
一般int都用long代替 char* 用 BSTR 代替
Long是四个字节 任何语言中都有四个字节的类型
BSTR 字符串类型 结构为 len + 字符串 + \0
因为有的语言字符串是 len 加字符串, 有的是\0结尾,为了统一,用BSTR 类型定义
一般指针指向字符串的位置,所以可以当char*使用。其他不一样的语言需要减个4字节
c语言转换方式
CString ---》 BSTR
CString str("Hello");
BSTR bstr = str.AllocSysString();
BSTR ---》 CString
CString str;
BSTR bstr = ::SysAllocString(OLESTR("Hello"));
str = bstr;
c++转换 _bstr_t 是一个类
_bstr_t ---》 CString
CString str;
_bstr_t bstr("Hello");
bstr += "World";
str = (BSTR)bstr;
char *p = (char*)bstr;
CString ---》 _bstr_t
CString str("hello");
_bstr_t bstr(str);
BSTR bstr2 = (BSTR)bstr;
加载dll两种方式
一种LoadLibrary 哪里需要的时候加载 将指定的模块加载到调用进程的地址空间中
一种#pragma comment 程序运行开始会编译
导出函数加上PRIVATE私有 导出函数就会不是你de函数名。防止dll劫持
因为使用函数查注册表,加载dll 导出类工厂,导出类代码基本上是一样的,所以封装了函数方便调用
Windows封装的两个函数
CoCreateInstance 产生工厂
CoGetClassObject产生对象
CComPtr<ISuperMath> ptr; 系统封装的智能指针
自己实现的如下代码:
//1.查注册表
char Guid[60];
GUID2String(clsid, Guid);
char Subkey[260];
wsprintf(Subkey, "CLSID\\{%s}\\InprocServer32", Guid);
char Path[MAX_PATH];
LONG size;
RegQueryValue(HKEY_CLASSES_ROOT, Subkey, Path, &size);
//2.加载dll
HRESULT hr;
HMODULE hDll = LoadLibrary(Path);
if (hDll == NULL)
return S_FALSE;
MY_GET_CLASS_OBJECT pfnGetClassObject = (MY_GET_CLASS_OBJECT)GetProcAddress(hDll, "DllGetClassObject");
if (pfnGetClassObject == NULL)
return S_FALSE;
产生工厂
hr = pfnGetClassObject(clsid, iid, ppObject);
if (FAILED(hr))
return hr;
产生对象
hr = pClassFactroy->CreateObject(iid, ppObject);
if (FAILED(hr))
return hr;
加载dll想要使用还需要包含头文件,为了使其他语言函数定义特别发明了一种语言只能写函数声明;
IDL是用来描述软件组件接口的一种计算机语言。
TLB(Translation Lookaside Buffer)转换检测缓冲区是一个内存管理单元,用于改进虚拟地址到物理地址转换速度的缓存。
首先需要在 idl文件中写函数声明,在通过midl转换成tlb文件
Midl 全称Microsoft Interface Definition Language,即接口定义语言。它是微软的一个产品,定义了客户程序与服务器程序之间的接口
Idl语言
Class -》 interface Include -》 import
加入了[]属性描述 in 传入 out传出 retral 返回值
文本类 注释// 或者/**/ 文本外显示注释 [helpstring(“注释内容”)]
实例:
import "unknwn.idl";
[
object,
uuid(2729A764-828A-46c9-9E53-842EEAFB323D)
]
interface IMyString : IUnknown
{
[helpstring("初始化字符串")]
HRESULT InitData([in]BSTR bstrInit);
[helpstring("获取字符串")]
HRESULT GetData([out, retval]BSTR *pbstrResult);
[helpstring("获取字符串长度")]
HRESULT GetLength([out, retval]long *plLen);
};
Object:是指定接口是COM接口的方法。
Uuid:这指定了接口的GUID,使接口被唯一的标示。
Helpstring:最大长度255字节
coclass(组件自动化)
这个表达式描述一个组件对象模型(COM)的全球统一标识符和它支持的接口.
[attributes]
coclass classname {
[attributes2] [interface | dispinterface] interfacename;
};
语法元素:
attributes
在coclass表达式中,uuid属性是必须的.这个uuid与在系统注册表中注册组件的CLSID是相同的.在本表达式的前面还接受 helpstring , helpcontext , version , licensed , control , hidden 与 appobject 属性,但不是必须的.想了解这些属性更多的细节,请看下一章.appobject 属性使 coclass 的函数和属性在整个类型库内有效.
classname
在类型库中标识普通对象的名字.
attributes2
interface或dispinterface的可选属性.source , default 与 restricted 属性可以被接受.
interfacename
用 interface 或 dispinterface 声明的接口.
备注
组件对象模型定义一个类作为一个实现,允许QueryInterface在接口集之间查询.