C++

VC++中import的使用

Posted by Kerwen Blog on June 1, 2015

import 指令

1. C++中使用 COM 简单的方法是

用 import 导入 type library

2. # import 指令将 COM 产生对应的 C++类别

可以用接近于VBScript和Visual Basic的语句操作 COM

3. 使用 import 命令就可以将该文件导入到我们的程式码中。

type library 的内容将被转换为描述了 COM Interface 的 COM smart pointer

4. 语法

import “filename” [attributes]
import <filename> [attributes]

attributes:
用来通知编译器修改 type library header 的内文。可以使用空白或逗号分隔 attribute。该选项为选择性。如果 attribute 太多,可以使用 / 断行分隔
a) auto_rename
b) auto_search
c) embedded_idl
d) exclude
e) high_method_prefix
f) high_property_prefixes
g) implementation_only
h) include()
i) inject_statement
j) named_guids
k) no_auto_exclude
l) no_dual_interfaces
m) no_implementation no_namespace
n) no_search_namespace
o) no_smart_pointers
p) raw_dispinterfaces
q) raw_interfaces_only
r) raw_method_prefix
s) raw_native_types
t) raw_property_prefixes
u) rename
v) rename_namespace
w) rename_search_namespace
x) tlbid
filename:
你想要汇入的 type library,可以指定的值如下
a) type library (.tlb, .odl): import “drawctl.tlb”
b) ProgID: import “progid:my.prog.id.1.5”
可以额外指定地区ID和版本号码,如下:
import “progid:my.prog.id” lcid(“0”) version(“4.0)
假如没有指定地区 ID 会依循下列规则自动选择
1) 假如只有一个地区 ID 就直接使用
2) 假如有多个地区 ID,选择版本编号的第一码为 0, 9 或 499 的使用
3) 假如有多个地区 ID,且版本编号的第一码为 0, 9 或 499 有多个可以选择,则选用最后一个
4) 假如没有指定版本号码,则使用最近的版本号码
c) type library ID: import “libid:12341234-1234-1234-1234-123412341234” version(“4.0”) lcid(“9”)
d) 一个可执行档(.exe)
e) 包含 type library 资讯的 dll
f) 内含 type library 的文件
g) 任何可被 LoadTypeLib 接受的档案
filename 如果为一个实体档案,会依循下面的规则进行搜寻
1) import 中指定的路径
2) 引用该档案的程式所在路径
3) PATH 环境变数
4) LIB 环境变数
5) 编译器选项 /I 指定的路径

5. import 产生的 header 档

包含类似 MIDL(Microsoft Interface Definition Language) 产生的主要 header 档,但是包含额外的编译器产生的程式码和资料。该档案和 type library 具有相同的名称但附档名为 .tlh。第二个 header 档也具有和 type library 相同的档名,但附档名为 .tli。他内含编译器产生的成员函式的实作,且该 header 被包含在主要 header 档(.tlh)中。
假如併入(import)一个包含 byref 参数的 dispinterface property, import 将不会产生 __declspec (property) 叙述
这两个 header 放置在 /Fo 指定的目录,
import 在接到 type library 同时间会产生 header 档。当 import 处理完,编译器会检查档案是否存在并且日期够新。假如条件吻合则不重新建立。
import 指令也可以放在预先编译的 header 中,详请参考 http://msdn.microsoft.com/library/en-us/vccore/html/_core_Creating_Precompiled_Header_Files.asp

6. 主要的 header (.tlh)包含七个部分

a) 固定的标头:包含注解、#include “COMDEF.h”和其他安装资讯
b) 向前参照和 typdef
c) 智慧型指标宣告:样板类别 _com_ptr_t 属于一个智慧型指标,该类别封装了介面指标并排除呼叫 AddRef, Release, QueryInterface 等繁琐的步骤。另外也隐藏了 CoCreateInstance 建立一个新的 COM 物件的呼叫。这个部分使用 _COM_SMARTPTR_TYPEDEF 来产生特异化(Specialization)版本的 _com_ptr_t 类别。例如:
_COM_SMARTPTR_TYPEDEF(IMyInterface, __uuidof(IMyInterface));
编译器会将上述的程式扩展成
typedef _com_ptr_t<_com_IIID<IMyInterface, __uuidof(IMyInterface)> > IMyInterfacePtr;
d) Typeinfo 宣告
e) 旧型 GUIDE 定义:选择性部分,包含命名过的 GUID 常数 ,命名类似 CLSID_CoClass 和 IID_Interface,类似 MIDL 编译器产生的资料
f) #include 第二个 header (*.tli)
g) 档尾: #pragma pack(pop)

7. 使用 type library 可以用全域的解析或是明确的使用 namespace,如下

using namespace MyLib;
该程式码必须加在 import 之后。
可以使用 no_namespace attribute 不需指定 namespace,不过可能发生名称衝突。也可以使用 rename_namespace attribute 变更 namespace 名称。
参考资料:
[1] MSDN, http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/predir_The.23.import_Directive.asp
[2] Q242527 PRB: import Wrapper Methods May Cause Access Violation
[3] Q269194 PRB: Compiler Errors When You Use import with XML