365体育比分-华为怎么进BT365-365bet娱乐登陆

365体育比分

COM组件笔记(五)

2026-11-07 12:14:58 作者 admin 阅读 1065
COM组件笔记(五)

一、COM组件的注册

我们目前用ATL制作出来的简单对象是*.dll的形式,我们在之前的例子中能调用这个dll,是因为我们的VisualStudio在编译生成这个dll时,对它进行了注册。

如何手动注册COM组件:

1)打开控制台窗口(一般情况下要以管理员身份运行,因为注册COM组件的程序一般需要管理员权限):

2)查看注册的动态库信息,需要加载注册表:

查找对应的GUID信息

3.对COM组件进行注册的意义:

我们刚才从注册表中看到了注册信息记录了组件的CLSID,组件的路径,组件的PropID等。

而我们的COM组件是跨应用的,网页,MFC,C#的WinForm,VB需要识别并创建我们的组件。最终需要得到我们组件的路径。而路径是可能改变的,比如用户安装程序时选择不同目录,CLSID跟PropID是不变 的,我们采用CLSID或PropID去创建组件,不管COM组件的ll在哪个位置,都跟我们的创建代码无关。

从vista开始,注册需要权限了,我们可以做一个不需要注册的COM。这个内容放到以后高级编程中来讲。

二、智能指针的使用

C++在调用COM接口指针时是很危险的,因为使用过程需要每一个使用都严格并且正确地调用AddRef()与Release()方法。一旦出现问题,就会造成对象不能被正常释放或者对象被重复删除。

所以C++程序员使用COM接口时,得小心翼翼的。有没有办法改变这种现状,让我们的编程过程更简单呢?答案是有的,那就是智能指针。

CComPtr是智能指针,是ATL提供的一个模板类,能封装COM接口的AddRef()与Release()方法。

CComPtr声明出来的变量是一个对象,这个对象封装了COM接口指针,这个对象的使用访问跟COM接口的使用方法几乎一样。

案例:

1 // 案例在MFC下进行,函数写在一个按钮中

2 void CMFCTestSectionDemo1Dlg::OnBnClickedButton1()

3 {

4 // TODO: 在此添加控件通知处理程序代码

5 #pragma region 不使用智能指针

6 HRESULT hr = E_FAIL;

7 hr = CoInitialize(NULL); // 使用com组件之前要添加这一句,用COM组件的入口点

8

9 if (SUCCEEDED(hr)) {

10 IHelloSimpleObject* pIHelloSimpleObject = NULL;

11 hr = CoCreateInstance(CLSID_HelloSimpleObject, NULL,

12 CLSCTX_INPROC_SERVER, IID_IHelloSimpleObject, (void**)&pIHelloSimpleObject);

13 if (SUCCEEDED(hr)) {

14

15 // 加法方法测试

16 LONG lSum = 0;

17 hr = pIHelloSimpleObject->SumLong(9, 99, &lSum);

18

19 // 读描述属性

20 BSTR bstrDescriptionA = SysAllocString(L"");

21 hr = pIHelloSimpleObject->get_Description(&bstrDescriptionA);

22 SysFreeString(bstrDescriptionA);

23 bstrDescriptionA = NULL;

24

25 // 写属性描述

26 BSTR bstrDescriptionB = SysAllocString(L"我运行在MFC中,我是新的描述属性!");

27 hr = pIHelloSimpleObject->put_Description(bstrDescriptionB);

28 SysFreeString(bstrDescriptionB);

29 bstrDescriptionB = NULL;

30

31 // 读描述属性

32 BSTR bstrDescriptionC = SysAllocString(L"");

33 hr = pIHelloSimpleObject->get_Description(&bstrDescriptionC);

34 SysFreeString(bstrDescriptionC);

35 bstrDescriptionA = NULL;

36 }

37 pIHelloSimpleObject->Release(); // 不适用这个函数,引用计数减1

38 }

39

40 CoUninitialize(); //不使用com组件对象时添加这一句,用COM组件的出口点

41 #pragma endregion

42

43 #pragma region 使用智能指针

44 HRESULT hr = E_FAIL;

45 hr = CoInitialize(NULL);

46

47 if (SUCCEEDED(hr)) {

48 CComPtr spHelloSimpleObject;

49 hr = spHelloSimpleObject.CoCreateInstance(CLSID_HelloSimpleObject);

50 /*

51 * 对比以下

52 hr = CoCreateInstance(CLSID_HelloSimpleObject, NULL,

53 CLSCTX_INPROC_SERVER, IID_IHelloSimpleObject, (void**)&pIHelloSimpleObject);

54 */

55 if (SUCCEEDED(hr)) {

56 // 加法方法测试

57 LONG lSum = 0;

58 hr = spHelloSimpleObject->SumLong(9, 99, &lSum);

59

60 // 读描述属性

61 BSTR bstrDescriptionA = SysAllocString(L"");

62 hr = spHelloSimpleObject->get_Description(&bstrDescriptionA);

63 SysFreeString(bstrDescriptionA);

64 bstrDescriptionA = NULL;

65

66 // 写描述属性

67 BSTR bstrDescriptionB = SysAllocString(L"我运行在MFC中,我是新的描述属性!");

68 hr = spHelloSimpleObject->put_Description(bstrDescriptionB);

69 SysFreeString(bstrDescriptionB);

70 bstrDescriptionB = NULL;

71

72 // 读描述属性

73 BSTR bstrDescriptionC = SysAllocString(L"");

74 hr = spHelloSimpleObject->get_Description(&bstrDescriptionC);

75 SysFreeString(bstrDescriptionC);

76 bstrDescriptionC = NULL;

77 }

78

79 // spHelloSimpleObject->Release(); 不需要调用,也不能调用

80 }

81

82 CoUninitialize();

83 #pragma endregion

84

85 }

三、智能指针与COM接口指针的比较

CComPtr spHelloSimpleObject 创建了一个智能指针,其它是一个类对象,对象内部有一个IHelloSimpleObjectt*的指针变量,并且被初始化为NULL。

IHelloSimpleObject *pIHelloSimpleObject,一个原始的COM接口指针。

二者对->的操作的用法与意义一样。因为对智能指针的->操作会转换为对 _NoAddRefReleaseOnCComPtr* 变量的->操作。 _NoAddRefReleaseOnCComPtr是 IHelloSimpleObjectSub的子类。

不过智能指针不能执行->AddRef()与->Release()。因为_NoAddRefReleaseOnCComPtr类把AddReft()与Release()方法的访问权限设置为private。如果智能指针执行->AddRef()与->Release(),编译时,直接报错。

智能指针禁用->AddRef()与->Release()的原因是智能指针封装了COM接口指针的AddRef与Release操作,会智能判断何时对象内部会调用COM接口的AddRef,何时调用COM接口的Release。

之前对COM接口指针的赋值是需要做AddRef操作来添加引用计数,如果采用智能指针,它会智自地执行AddRef我们不必为此担心。

之前不再使用COM接口指针时,需要做Release操作来减少引用计数,如果采用智能指针,它会在对象销毁时(析构时),做COM接口指针的Release操作。

智能指针的变量是一个对象。

如果是局部变量,将在这个局部变量生命期结束时行智能指针的析构函数;

如果是成员变量,将在成员所在的类对象销毁时,执行智能指针的析构函数;

如果是静态变量,将在程序结束时,执行智能指针的析构函数。

四、智能指针的注意点

如果要释放一个智能指针直接给它赋NULL值就可以了。这样内部的COM接口指针也会执行Release操作,来减少引用计数;

当对智能指针取地址时(&运算符操作),要确保智能指针为NULL,因为&是要返回内部的COM接口指针的,如果不为NULL,则旧的COM接口指针将没有执行Release而直接赋值了一个旧的COM接口指针;

不过大家可以放心,因为如果这时智能指针不为NULL时,智能指的代码会通过assert断言报错,从而提醒程序员进行相应代码的更改。

相关文章