插件规范

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在接口集之间查询.

 

 

posted @ 2020-09-02 16:43  特权E5  阅读(184)  评论(0编辑  收藏  举报