|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
C#跟java类似,但是在跨平台方面理论上可以跨平台,实际上应用不大,执行性能优于java,跟C++基本一致,但是启动速度还是慢.代码安全,但容易性能陷阱.1、媒介
上两回中,我们用ATL写了第一个COM组件程序,这回中,次要先容编译、注册和挪用办法。示例程序你已下载了吗?假如还没有下载,vc6.0的用户点这里,vc.net的用户点这里。
2、关于编译
2-1最小依附
“最小依附”,暗示编译器会把ATL中必需利用的一些函数静态毗连到方针程序中。如许方针文件尺寸会稍年夜,但自力性更强,安装便利;反之体系实行的时分必要有ATL.DLL文件的撑持。怎样选择设置为“最小依附”呢?谜底是:删除预界说宏“_ATL_DLL”,操纵办法见、图二。
<br>
、在vc6.0中,设置办法
<br>
、在vc.net2003中,设置办法
2-2CRT库
假如在ATL组件程序中挪用了CRT的运转时候库函数,好比开平方sqrt(),那末编译的时分大概会报错“errorLNK2001:unresolvedexternalsymbol_main”。怎样办?删除预界说宏“_ATL_MIN_CRT”!操纵办法也见、图二。(vc.net2003中的这个项目属性叫“在ATL中最小利用CRT”)
2-3MBCS/UNICODE
这个未几说了,在预界说宏中,分离利用_MBCS或_UNICODE。
2-4IDL的编译
COM在计划早期,就定了一个方针:要能完成跨言语的挪用。既然是跨言语的,那末组件的接口形貌就必需在任何言语情况中都要可以熟悉。怎样办?用.h文件形貌?------C言语程序员笑了,真便利!BASIC程序员哭了:-(因而,微软利用了一个新的文件格局---IDL文件(接口界说形貌言语)。IDL是一个文本文件,它的言语语法对照复杂,很象C。详细IDL文件的解说,见下一回《COM组件计划与使用(八)之增加新接口》。IDL经由编译,天生二进制的等价范例库文件TLB供应给别的言语来利用。图三表示了ATLCOM程序编译的历程:
<br>
、ATL组件程序编译历程
申明1:编译后,范例库以TLB文件情势独自存在,同时也保留在方针文件的资本中。因而,我们未来在#import引进范例库的时分,既能够指定TLB文件,也能够指定方针文件;
申明2:我们作为C/C++的程序员,还算是对照幸运的。由于IDL编译后,特地为我们供应了C言语情势的接口文件。
申明3:IDL编译后天生代办署理/存本源程序,有:dlldata.c、xxx_p.c、xxxps.def、xxxps.mak,我们能够用NMAKE.EXE再次编译来发生真实的代办署理/存根DLL方针文件(注1)。
3、关于注册
情形1:当我们利用ATL编写组件程序,注册不必我们来卖力。编译乐成后,IDE会帮我们主动注册;
情形2:当我们利用MFC编写组件程序,因为编译器不晓得你写的是不是是COM组件,以是它不会帮我们主动注册。这个时分,我们能够实行菜单“ToolsRegisterControl”来注册。
情形3:当我们写一个具有COM功效的EXE程序时,注册的办法就是运转一次这个程序;
情形4:当我们必要利用第三方供应的组件程序时,能够命令交运行“regsvr32.exe文件名”来注册。特地说一句,反注册的办法是“regsvr32.exe/u文件名”;
情形5:当我们必要在程序中(好比安装程序)必要实行注册,那末:- typedefHRESULT(WINAPI*FREG)();TCHARszWorkPath[MAX_PATH];::GetCurrentDirectory(sizeof(szWorkPath),szWorkPath); //保留以后历程的事情目次::SetCurrentDirectory(组件目次); //切换到组件的目次HMODULEhDLL=::LoadLibrary(组件文件名); //静态装载组件if(hDLL){FREGlpfunc=(FREG)::GetProcAddress(hDLL,_T("DllRegisterServer")); //获得注册函数指针//假如是反注册,能够获得"DllUnregisterServer"函数指针if(lpfunc) lpfunc(); //实行注册。这里为了复杂,没有判别前往值::FreeLibrary(hDLL);}::SetCurrentDirectory(szWorkPath); //切换回本来的历程事情目次
复制代码 下面的示例,在多半情形下能够简化失落切换事情目次的代码部分。可是,假如这个组件在装载的时分,它必要同时加载一些必需依附的DLL时,有大概因为它本身程序的BUG招致没法准确定位。咳......仍是让我们本人写的程序,来填补它的毛病吧......谁让我们是坏人呢,谁让我们的程度比他高呢,谁让我们在vckbase上是个“榜眼”呢......
4、关于组件挪用
总的来讲,挪用组件程序也许有以下办法:
#include办法IDL编译后,为便利C/C++程序员的利用,会发生xxx.h和xxx_i.c文件。我们真幸运,间接#include后就能够利用了#import办法对照通用的办法,vc会帮我们发生包装类,让我们的挪用更便利加载范例库包装类办法假如组件供应了IDispatch接口,用这个办法挪用组件是最复杂的啦。不外还没讲IDispatch,只能看今后的文章啦加载ActiveX包装类办法ActiveX还没先容呢,今后再说啦 下载示例程序后,请逐项扫瞄利用办法:
示例办法
扼要申明
1#include完整用最基础的API体例挪用组件,使人人熟习挪用道理2#include年夜部分利用API体例,利用CComBSTR简化对字符串的利用3#include展现智能指针CComPtr的利用办法4#include展现智能指针CComPtr和CComQIPtr夹杂的利用办法5#include展现智能指针CComQIPtr的利用办法6#include展现智能指针的开释办法7#importvc包装的智能指针IxxxPtr、_bstr_t、_variant_t的利用办法和非常处置8#importimport后的定名空间的利用办法 示例程序中都写有正文,请读者细心浏览并同时参考MSDN的函数申明。这里,我给人人先容一下“智能指针”:
关于操纵原始的接口指针是对照贫苦的,必要我们本人把持援用记数、API挪用、非常处置。因而ATL供应了2个智能指针的模板包装类,CComPtr和CComQIPtr,这两个类都在<atlbase.h>中声明。CComQIPtr包括了CComPtr的一切功效,因而我们能够完整用CComQIPtr来利用智能接口指针,独一要申明的一点就是:CComQIPtr因为利用了运算符的重载功效,它会主动帮我们挪用QueryInterface()函数,因而CComQIPtr独一的弱点就是不克不及界说IUnknown*指针。- //智能指针smartpointer,依照匈牙利定名法,一样平常以sp开首来暗示变量范例 CComPtr<IUnknown>spUnk; //准确 //假定IFun是一个接口范例 CComPtr<IFun>spFun; //准确 CComQIPtr<IFun>spFun; //准确 CComQIPtr<IFun,&IID_IFun>spFun; //准确 CComQIPtr<IUnknown>spUnk; //毛病!CComQIPtr不克不及界说IUnknown指针
复制代码 给智能指针赋值的办法:- CComQIPtr<IFun>spFun; //挪用机关函数,还没有赋值,被包装的外部接口指针为NULL CComQIPtr<IFun>spFun(pOtherInterface); //挪用机关函数,外部接口指针赋值为 //经由过程pOtherInterface这个一般接口指针挪用QueryInterface()失掉的IFun接口指针 CComQIPtr<IFun>spFun(spOtherInterface);//挪用机关函数,外部接口指针赋值为 //经由过程spOtherInterface这个只能接口指针挪用QueryInterface()失掉的IFun接口指针 CComQIPtr<IFun>spFun(pUnknown); //挪用机关函数,由IUnknown的QueryInterface()失掉IFun接口指针 CComQIPtr<IFun>spFun=pOtherInterface; //=运算符重载,寄义和下面一样 spFun=spOtherInterface; //同上 spFun=pUnknown; //同上 pUnknown->QueryInterface(IID_IFun,&sp); //也能够经由过程QueryInterface赋值 //智能指针赋值后,能够用前提语句判别是不是正当无效 if(spFun){}//假如指针无效 if(NULL!=spFun){} //假如指针无效 if(!spFun){}//假如指针有效 if(NULL==spFun){} //假如指针有效
复制代码 智能指针挪用函数的办法:- spFun.CoCreateInstance(...); //等价与API函数::CoCreateInstance(...) spFun.QueryInterface(...); //等价与API函数::QueryInterface() spFun->Add(...); //挪用外部接口指针的接口函数 //挪用外部接口指针的QueryInterface()函数,实在效果和spFun.QueryInterface(...)一样 spFun->QueryInterface(...); spFun.Release(); //开释外部的接口指针,同时外部指针赋值为NULL spFun->Release(); //错!!!必定不要这么利用。 //由于这个挪用其实不把外部指针清空,那末析构的时分会被再次开释(开释了两次)
复制代码 咳......不说了,不说了,人人多看书,多看MSND,多看示例程序吧。写累了:-(
5、小结
敬请存眷《COM组件计划与使用(八)》------怎样增添ATL组件中的第二个接口
注1:编译代办署理/存根,vc6.0中略微贫苦,我们在前面先容“历程外组件”和“远程组件”的时分再先容。在vc.net2003下则对照复杂,由于代办署理/存根作为独自的一个工程项目会主动加到我们的办理计划中了。
原文链接:http://www.vckbase.com/document/viewdoc/?id=1500
再举这样一个例子:如果你想对一个数字取绝对值,你会怎么做呢?java的做法是intc=Math.abs(-166);而ruby的做法是:c=-166.abs。呵呵,这就看出了java与ruby的区别。 |
|