Type Library
(一) 用途?
只要用到IDispatch的地方,几乎都需要用到Type Library。
那如果用到IDispatch而不想Type Library可以吗?答案可以肯定是可以的,但会很麻烦。下面会讲到为什么非用Type libreary不可。
(二) Type libreary生存在何地?
生存在DLL或EXE文件里面。
(三) 如何获得?
可以用LoadTypeLib或者LoadRegTypeLib,前者从文件载入,后者从注册表获得,但最终还是从文件获得。
(四) 如何让Type libreary生存在EXE或DLL里面
如果使用ATL,从工程出生开始就已经有Type libreary。
非ATL如何手工添加呢?
1. 添加IDL文件
2. 在IDL文件里添加lbirary
添加IDL后之后IDE会只自动生成2行代码
import "oaidl.idl"; import "ocidl.idl";
|
需要添加一个library,这个library就是Type libreary生存的地方,相当于C语言的main函数一样。添加完如下图
import "oaidl.idl"; import "ocidl.idl"; [ uuid(95667A6D-8312-4539-B185-89EDECC76CB2), version(1.0), helpstring("MyLibrary 1.0 Type Library") ] library MyLibrary { importlib("stdole32.tlb"); importlib("stdole2.tlb"); }; |
3. 编译IDL文件
仅仅编译IDL,不需果编译其它东西。
在Debug或者在Release里会生成tlb文件,其名字默认为:$(ProjectName).tlb
4. 在Resource 里添加tlb
右击资源
选择Resource Includes…
在“Compile-time directives:”栏里填入刚才编译完的IDL生成的tlb文件。格式如下:
1 TYPELIB "myidl.tlb(上图的名字仅供参考)
现在编译一次,就能准确的生成TypeLibrary.
为了确认是否已经生成的TypeLibrary,可以使用OLE/COM Object Viewer来进行查看
点击工具栏的三个红角那个图标,选择EXE,DLL或者TLB,就可以看到相应的信息,如下图:
如果报错,那么刚才没有准确的生成TLB。
(五) 为什么要非使用TLB不可呢?
因为在IDispatch里规范里就有函数
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo( UINT iTInfo, LCID lcid,ITypeInfo **ppTInfo) = 0;
需要ppTInfo信息。
所以如果DLL或EXE是作为服务器端,那是必须要需要TLB的。
但如果程序作为客户端,简单的说,就是作为连接点的客户端,需要提供个IDispatch接口给服务器,这种情况下,不一定需要真实的TLB,那个时候最重要的是Invoke函数嘛。
但为什么最好需要TLB呢?
因为ATL提供的类IDispathcImpl和IDispEventImpl都需要真实的TLB信息。
(六) 使用方法:
1. 需要注册的情况
简单的说,用到rgs文件往注册表里写入信息的情况,这个时候,可以这样写
public IDispatchImpl<IMyDispEvent,&IID_IMyDispEvent,&LIBID_WTLEvent >
public IDispEventImpl<EVENT_CTRLID3,CWTLEventView,&IID_IMyDispEvent,&LIBID_WTLEvent>
相当普通的写法。这两个类在获类型信息的时候,会使用LoadRegTypeLib
2. 不需要注册的情况
这种情况下,不能使用默认版本号
public IDispatchImpl<IMyDispEvent,&IID_IMyDispEvent,&LIBID_WTLEvent, 0xFFFF, 0xFFFF >
public IDispEventImpl<EVENT_CTRLID3,CWTLEventView,&IID_IMyDispEvent,&LIBID_WTLEvent, 0xFFFF, 0xFFFF >
这两个类在获类型信息的时候,会使用LoadTypeLib
(七) 注意事项
1. WTL或者其它项目的时候使用IDispatchImpl和IDispEventImpl的时候,必须需要全局的CAtlModule 对象,并且对其m_libid赋入LIBID值
CAtlModule::m_libid=LIBID_Mylib;
2. 添加完IDL后,编译IDL可能会成XXX_i.c,XXX_p.c和XXX.h,需要加XXX_p.c加入工程,并将其链接设为预编译头文件修改一下:
3. 为什么需要到RC文件里添加1 TYPELIB "myidl.tlb"呢?
在工程属性的链接的Embedded IDL项中的
TypeLib Resource ID里的ID为1。当然可以把这个ID改成2,然后资源文件改成2 TYPELIB "myidl.tlb"