COM技术初探二.docx
- 文档编号:18105570
- 上传时间:2023-08-13
- 格式:DOCX
- 页数:28
- 大小:89.31KB
COM技术初探二.docx
《COM技术初探二.docx》由会员分享,可在线阅读,更多相关《COM技术初探二.docx(28页珍藏版)》请在冰点文库上搜索。
COM技术初探二
三、纯手工创建一个COM组件
1、从建工程到实现注册
在这一过程中我们将完成三个步骤:
创建dll的入口函数,定义接口文件,实现注册功能
1.1创建一个类型为win32dll工程
创建一个名为MathCOM的win32dll工程。
在向导的第二步选择"Asmipledllproject"选项。
当然如果你选择一个空的工程,那你自己完成DllMain定义吧。
1.2定义接口文件
生成一个名为MathCOM.idl的接口文件。
并将此文件加入到刚才创建的那个工程里。
viewsource
print?
01.//MathCOM.idl文件
02.//MathCOM.idl:
IDLsourceforMathCOM.dll
03.//
04.//ThisfilewillbeprocessedbytheMIDLtoolto
05.//producethetypelibrary(MathCOM.tlb)andmarshallingcode.
06.import"oaidl.idl";
07.import"ocidl.idl";
08. [
09. uuid(FAEAE6B7-67BE-42a4-A318-3256781E945A),
10. helpstring("ISimpleMathInterface"),
11. object,
12. pointer_default(unique)
13. ]
14. interfaceISimpleMath:
IUnknown
15. {
16. HRESULTAdd([in]intnOp1,[in]intnOp2,[out,retval]int*pret);
17. HRESULTSubtract([in]intnOp1,[in]intnOp2,[out,retval]int*pret);
18. HRESULTMultiply([in]intnOp1,[in]intnOp2,[out,retval]int*pret);
19. HRESULTDivide([in]intnOp1,[in]intnOp2,[out,retval]int*pret);
20. };
21.
22. [
23. uuid(01147C39-9DA0-4f7f-B525-D129745AAD1E),
24. helpstring("IAdvancedMathInterface"),
25. object,
26. pointer_default(unique)
27. ]
28. interfaceIAdvancedMath:
IUnknown
29. {
30. HRESULTFactorial([in]intnOp1,[out,retval]int*pret);
31. HRESULTFabonacci([in]intnOp1,[out,retval]int*pret);
32. };
33.[
34. uuid(CA3B37EA-E44A-49b8-9729-6E9222CAE844),
35. version(1.0),
36. helpstring("MATHCOM1.0TypeLibrary")
37.]
38.
39.
40.
41.
42.libraryMATHCOMLib
43.{
44. importlib("stdole32.tlb");
45. importlib("stdole2.tlb");
46.
47. [
48. uuid(3BCFE27E-C88D-453C-8C94-F5F7B97E7841),
49. helpstring("MATHCOMClass")
50. ]
51. coclassMATHCOM
52. {
53. [default]interfaceISimpleMath;
54. interfaceIAdvancedMath;
55. };
56.};
在编译此工程之前请检查Project/Setting/MIDL中的设置。
正确设置如下图:
图1.4 midl的正确设置
在正确设置后,如编译无错误,那么将在工程的目录下产生四个
文件名
作用
MathCOM.h
接口的头文件,如果想声明或定义接口时使用此文件
MathCOM_i.c
定义了接口和类对象以及库,只有在要使用到有关与GUID有关的东西时才引入此文件,此文件在整个工程中只能引入一次,否则会有重复定义的错误
MathCOM_p.c
用于存根与代理
dlldata.c
不明
1.3增加注册功能
作为COM必须要注册与注销的功能。
1.3.1增加一个MathCOM.def文件
DEF文件是模块定义文件(ModuleDefinitionFile)。
它允许引出符号被化名为不同的引入符号。
viewsource
print?
01.//MathCOM.def文件
02.;MathCOM.def:
Declaresthemoduleparameters.
03.
04.LIBRARY "MathCOM.DLL"
05.
06.EXPORTS
07. DllCanUnloadNow @1PRIVATE
08. DllGetClassObject @2PRIVATE
09. DllRegisterServer @3PRIVATE
10. DllUnregisterServer@4PRIVATE
DllUnregisterServer 这是函数名称@4<――这是函数序号PRIVATE
接下来大致介绍一下DllRegisterServer()和DllUnregisterServer()。
(其他两个函数的作用将在后面介绍)
1.3.2DllRegisterServer()和DllUnregisterServer()
DllRegisterServer()函数的作用是将COM服务器注册到本机上。
DllUnregisterServer()函数的作用是将COM服务器从本机注销。
1.4MathCOM.cpp文件
现在请将MathCOM.cpp文件修改成如下:
viewsource
print?
01.//MATHCOM.cpp:
DefinestheentrypointfortheDLLapplication.
02.//
03.#include"stdafx.h"
04.#include
05.#include
06.#include"MathCOM.h"
07.//standardself-registrationtable
08.constchar*g_RegTable[][3]={
09. {"CLSID\\{3BCFE27E-C88D-453C-8C94-F5F7B97E7841}",0,"MathCOM"},
10. {"CLSID\\{3BCFE27E-C88D-453C-8C94-F5F7B97E7841}\\InprocServer32",
11. 0,
12. (constchar*)-1/*表示文件名的值*/},
13. {"CLSID\\{3BCFE27E-C88D-453C-8C94-F5F7B97E7841}\\ProgID",0,"tulip.MathCOM.1"},
14. {"tulip.MathCOM.1",0,"MathCOM"},
15. {"tulip.MathCOM.1\\CLSID",0,"{3BCFE27E-C88D-453C-8C94-F5F7B97E7841}"},
16.};
17.HINSTANCE g_hinstDll;
18.BOOLAPIENTRYDllMain(HANDLEhModule,
19. DWORD ul_reason_for_call,
20. LPVOIDlpReserved
21. )
22.{
23. g_hinstDll=(HINSTANCE)hModule;
24. returnTRUE;
25.}
26./*********************************************************************
27. *FunctionDeclare:
DllUnregisterServer
28. *Explain:
self-unregistrationroutine
29. *Parameters:
30. *void--
31. *Return:
32. *STDAPI --
33. *Author:
tulip
34. *Time:
2003-10-2919:
07:
42
35.*********************************************************************/
36.STDAPIDllRegisterServer(void)
37.{
38. HRESULThr=S_OK;
39. charszFileName[MAX_PATH];
40. :
:
GetModuleFileName(g_hinstDll,szFileName,MAX_PATH);
41.
42. intnEntries=sizeof(g_RegTable)/sizeof(*g_RegTable);
43. for(inti=0;SUCCEEDED(hr)&&i 44. { 45. constchar*pszKeyName=g_RegTable[i][0]; 46. constchar*pszValueName=g_RegTable[i][1]; 47. constchar*pszValue=g_RegTable[i][2]; 48. 49. if(pszValue==(constchar*)-1) 50. { 51. pszValue=szFileName; 52. } 53. 54. HKEYhkey; 55. longerr=: : RegCreateKey(HKEY_CLASSES_ROOT,pszKeyName,&hkey); 56. if(err==ERROR_SUCCESS) 57. { 58. err=: : RegSetValueEx(hkey, 59. pszValueName, 60. 0, 61. REG_SZ, 62. (constBYTE*)pszValue, 63. (strlen(pszValue)+1)); 64. : : RegCloseKey(hkey); 65. } 66. if(err! =ERROR_SUCCESS) 67. { 68. : : DllUnregisterServer(); 69. hr=E_FAIL; 70. } 71. 72. } 73. returnhr; 74.} 75. 76.STDAPIDllGetClassObject(REFCLSIDrclsid,REFIIDriid,void**ppv) 77.{ 78. returnCLASS_E_CLASSNOTAVAILABLE; 79.} 80. 81.STDAPIDllCanUnloadNow(void) 82.{ 83. returnE_FAIL; 84.} 我只是在此文件中加几个必要的头文件和几个全局变量。 并实现了DllRegisterServer()和DllUnregisterServer()。 而对于其他两引出函数我只返回一个错误值罢了。 1.5小结 现在我们的工程中应该有如下文件: 文件名 作用 Stdafx.h和stdafx.cpp 预编译文件 MathCOM.cpp Dll入口函数及其他重要函数定义的地方 MathCOM.def 模块定义文件 MathCOM.idl 接口定义文件(在1.2后如果编译的话应该还有四个文件) 好了到现在,我的所谓COM已经实现注册与注销功能。 如果在命令行或"运行"菜单下项执行如下"regsvr32绝对路径+MathCOM.dll"就注册此COM组件。 在执行完此命令后,请查看注册表项的HKEY_CLASSES_ROOT\CLSID项看看3BCFE27E-C88D-453C-8C94-F5F7B97E7841这一项是否存在(上帝保佑存在)。 如同上方法再执行一下"regsvr32-u绝对路径+MathCOM.dll",再看看注册表。 其实刚才生成的dll根本不是COM组件,哈哈! ! ! 因为他没有实现DllGetClassObject()也没有实现ISmipleMath和IAdvancedMath两个接口中任何一个。 让我们继续前行吧! ! ! 2、实现ISmipleMath,IAdvancedMath接口和DllGetClassObject() 2.1实现ISmipleMath和IAdvancedMath接口 让我们将原来的CMath类修改来实现ISmipleMath接口和IAdvancedMath接口。 修改的地方如下: viewsource print? 01.1)Math.h文件 02./*@**#---2003-10-2921: 33: 44(tulip)---#**@ 03.#include"interface.h"*/ 04.#include"MathCOM.h"//新增加的,以替换上面的东东 05.classCMath: publicISimpleMath, 06.publicIAdvancedMath 07.{ 08.private: 09.ULONGm_cRef; 10.private: 11.intcalcFactorial(intnOp); 12.intcalcFabonacci(intnOp); 13.public: 14.CMath(); 15.//IUnknownMethod 16.STDMETHOD(QueryInterface)(REFIIDriid,void**ppv); 17.STDMETHOD_(ULONG,AddRef)(); 18.STDMETHOD_(ULONG,Release)(); 19.// ISimpleMathMethod 20.STDMETHOD(Add)(intnOp1,intnOp2,int*pret); 21.STDMETHOD(Subtract)(intnOp1,intnOp2,int*pret); 22.STDMETHOD(Multiply)(intnOp1,intnOp2,int*pret); 23.STDMETHOD(Divide)(intnOp1,intnOp2,int*pret); 24.// IAdvancedMathMethod 25.STDMETHOD(Factorial)(intnOp,int*pret); 26.STDMETHOD(Fabonacci)(intnOp,int*pret); 27.}; viewsource print? 01.2)Math.cpp文件 02./*@**#---2003-10-2921: 32: 35(tulip)---#**@ 03. 04. #include"interface.h" */ 05. #include"math.h" 06. 07. 08. STDMETHODIMPCMath: : QueryInterface(REFIIDriid,void**ppv) 09. {// 这里这是实现dynamic_cast的功能,但由于dynamic_cast与编译器相关。 10. if(riid==IID_ISimpleMath) 11. *ppv=static_cast 12. elseif(riid==IID_IAdvancedMath) 13. *ppv=static_cast 14. elseif(riid==IID_IUnknown) 15. *ppv=static_cast 16. else{ 17. *ppv=0; 18. returnE_NOINTERFACE; 19. } 20. 21. reinterpret_cast 22. returnS_OK; 23. } 24. 25. STDMETHODIMP_(ULONG)CMath: : AddRef() 26. { 27. return++m_cRef; 28. } 29. 30. STDMETHODIMP_(ULONG)CMath: : Release() 31. { 32. ULONGres=--m_cRef;//使用临时变量把修改后的引用计数值缓存起来 33. if(res==0) //因为在对象已经销毁后再引用这个对象的数据将是非法的 34. deletethis; 35. returnres; 36. } 37. 38. STDMETHODIMPCMath: : Add(intnOp1,intnOp2,int*pret) 39. { 40. *pret=nOp1+nOp2; 41. returnS_OK; 42. } 43. 44. STDMETHODIMPCMath: : Subtract(intnOp1,intnOp2,int*pret) 45. { 46. *pret=nOp1-nOp2; 47. returnS_OK; 48. } 49. 50. STDMETHODIMPCMath: : Multiply(intnOp1,intnOp2,int*pret) 51. { 52. *pret=nOp1*nOp2; 53. returnS_OK; 54. } 55. 56. STDMETHODIMPCMath: : Divide(intnOp1,intnOp2,int*pret) 57. { 58. *pret=nOp1/nOp2; 59. returnS_OK; 60. } 61. 62. intCMath: : calcFactorial(intnOp) 63. { 64. if(nOp<=1) 65. return1; 66. 67. returnnOp*calcFactorial(nOp-1); 68. } 69. 70. STDMETHODIMPCMath: : Factorial(intnOp,int*pret) 71. { 72. *pret=calcFactorial(nOp); 73. returnS_OK; 74. } 75. 76. intCMath: : calcFabonacci(intnOp) 77. { 78. if(nOp<=1) 79. return1; 80. 81. returncalcFabonacci(nOp-1)+calcFabonacci(nOp-2); 82. } 83. 84.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- COM 技术 初探