4.1 静态库与动态库

·DLL支持任何其他Windows下的编程语言,避免了编译器的兼容问题

·只要DLL中导出函数的接口不变,修改动态链接库的功能模块时就不必修改与之相互依存的其他模块的代码

·在同一个Windows操作系统下,不同的应用程序可以共享使用相同的DLL,可以减少应用程序可执行文件的大小,节省空间

·以DLL发布的程序可以给用户提供一个方便的二次开发平台而又不必担心自身源代码的泄漏

  

  

   一般情况下,编译生成DLL的时候导入库(.lib)文件会一同被创建。但若导入库文件丢失,在CVI中可以通过点击菜单Options-Generate DLL Import Library…来生成一个导入库文件。

  

  

  

labview调用teststand例程 labview调用文件_库文件

  

labview调用teststand例程 labview调用文件_头文件_02

labview调用teststand例程 labview调用文件_库文件_03

  

labview调用teststand例程 labview调用文件_库文件_04

  

labview调用teststand例程 labview调用文件_头文件_05

图 4‑1 新建的工程目录

  

labview调用teststand例程 labview调用文件_库文件_06

图 4‑2 工程运行结果

   若此时我们右击StaticLib工程中的Main.c文件,选择Exclude File from Build,如图 4‑3所示,然后点击CVI菜单-Build-Target Type-Static Library,将工程的输出由exe文件改为静态库文件,则编译之后,CVI将会编译未被排除在编译列表的StaticLib.c文件,并在工程目录下会生成一个名为“StaticLib.lib”的静态库文件。

labview调用teststand例程 labview调用文件_库文件_07

图 4‑3 将Main.c文件从编译列表中排除

   生成静态库文件之后,将StaticLib.c文件排除在编译列表之外,将刚生成的StaticLib.lib文件添加进工程中,并恢复Main.c文件到编译列表中,恢复工程编译生成的目标类型为可执行文件(菜单Build-Target Type-Executable)。此时工程目录如图 4‑4所示。

labview调用teststand例程 labview调用文件_头文件_08

图 4‑4 添加库文件的工程目录

  

labview调用teststand例程 labview调用文件_库文件_09

图 4‑5 从静态库中运行的结果

4.2 CVI生成DLL

4.2.1 CVI下生成DLL文件

   在上一节中,我们通过一个实例了解了在CVI下生成静态库文件的过程。生成DLL的步骤跟生成静态库的步骤基本相同,除了配置生成文件类型的时候选择“Dynamic Link Library”而不是“Static Library”之外。

  

labview调用teststand例程 labview调用文件_静态库_10

图 4‑6 CVI提示没有任何函数被导出

  

labview调用teststand例程 labview调用文件_头文件_11

图 4‑7 使用Depends程序查看DLL中发现不包含任何函数信息

   出现以上问题的原因在于,我们没有定义导出的函数库列表。点击CVI菜单-Build-Target Settings…之后,弹出如图 4‑8所示的窗口,在窗口中可以对生成的DLL进行设置。

labview调用teststand例程 labview调用文件_库文件_12

图 4‑8 设置目标DLL的属性

  

labview调用teststand例程 labview调用文件_头文件_13

图 4‑9 设置工程的导出内容

  

  

  

  

  

  

  

  

  

  

  

  

设置导出列表之后,Build工程,则CVI发出如图 4‑10所示的提示,告诉用户DLL已经成功生成。

labview调用teststand例程 labview调用文件_库文件_14

图 4‑10 DLL生成成功的提示

  

  

  

  

  

  

  

  

labview调用teststand例程 labview调用文件_静态库_15

图 4‑11 调用DLL文件的工程目录

  

labview调用teststand例程 labview调用文件_静态库_16

labview调用teststand例程 labview调用文件_库文件_17

  

labview调用teststand例程 labview调用文件_静态库_18

图 4‑12 调用DLL运行结果

  

  

  建立VC工程

  

labview调用teststand例程 labview调用文件_头文件_19

图 4‑13 在VC中新建控制台工程

  编写C语言文件

  

labview调用teststand例程 labview调用文件_库文件_20

  编译、调试

  

labview调用teststand例程 labview调用文件_库文件_21

  

  问题的原因

  

  

  

void foo( int x, int y );

  

  

  解决C++编译器兼容问题

  

labview调用teststand例程 labview调用文件_库文件_22

  

  

  

labview调用teststand例程 labview调用文件_头文件_23

  再次编译、运行

  

labview调用teststand例程 labview调用文件_库文件_24

图 4‑14 VC调用CVI生成的DLL运行测试

4.3 CVI调用DLL

  

  

  

  

  

  

labview调用teststand例程 labview调用文件_库文件_25

图 4‑15 LoadLibrary工程目录

  

labview调用teststand例程 labview调用文件_静态库_26

  

  

labview调用teststand例程 labview调用文件_头文件_27

图 4‑16 显示调用DLL文件运行结果

  

labview调用teststand例程 labview调用文件_静态库_28

  

生成DLL文件

  

  组建VC下的DLL工程

  

labview调用teststand例程 labview调用文件_库文件_29

图 4‑17 VC下新建一DLL工程

  

labview调用teststand例程 labview调用文件_库文件_30

  

labview调用teststand例程 labview调用文件_库文件_31

labview调用teststand例程 labview调用文件_静态库_32

  

labview调用teststand例程 labview调用文件_头文件_33

  

labview调用teststand例程 labview调用文件_库文件_34

图 4‑18 生成的DLL文件内部函数查看

  

  问题的原因

  

  

  

  

labview调用teststand例程 labview调用文件_库文件_35

图 4‑19 DLL文件中已经包含导出的SubTest函数

  

  

labview调用teststand例程 labview调用文件_头文件_36

  

labview调用teststand例程 labview调用文件_头文件_37

图 4‑20 CVI调用VC生成的DLL的运行测试

  

  

4.4 CVI调用.Net平台下的DLL

  

  

   CVI提供了帮助用户调用.Net程序集的.Net库。用户可以通过菜单-Tools-Create .Net Controller…向导生成可在CVI下使用的.Net库。通过使用CVI以及.Net库,我们可以完成以下工作:

·注册.Net控件并且加载控件

·创建.Net对象并且调用.Net对象

·管理系统资源

·创建.Net数组,并从.Net数据中获取元素

·获取.Net的错误与异常信息

·提供.Net组件的基本信息

·同COM组件交互操作

  

  

  

  

  

  

  

   一般如 Initialize_[命名空间] 和 Close_[命名空间] 两个函数分别调用 CDotNetLoadAssembly 和CDotNetDiscardAssemblyHandle 两个函数,[命名空间]_[类名称]__Create 调用CDotNetCreateGenericInstance 函数, [命名空间]_[类名称]_[函数名称] 调用CDotNetInvokeGenericStaticMember 函数等。

labview调用teststand例程 labview调用文件_静态库_38

图 4‑21 生成的仪器驱动函数树

   特别注意的是,由于被调用的DLL没有在全局程序集缓存(GAC,Global Assembly Cache)中,调用前需要使用CDotNetRegisterAssemblyPath函数先注册.NET的DLL。如果没有注册将出现如图4所提示的调用失败的错误。全局程序集缓存所在的文件夹为C:\WINDOWS\assembly。

labview调用teststand例程 labview调用文件_头文件_39

图 4‑22 .NET的DLL加载失败错误提示

  

  

  

   (2)调用CDotNetRegisterAssemblyPath("[DLL名称] , Version=x.x.x.x, Culture=xx , PublicKeyToken=xx" , ''Full Path of DLL")注册.NET的DLL,DLL的路径分隔符用"\",如D:\\CVI\\Projects\\C#net DLL call;

  

  

  

  

  

  

  

  

  新建C#类库工程

  

labview调用teststand例程 labview调用文件_库文件_40

图 4‑23 新建C#类库工程

  为工程添加密钥文件

  

  

labview调用teststand例程 labview调用文件_静态库_41

  

labview调用teststand例程 labview调用文件_头文件_42

labview调用teststand例程 labview调用文件_静态库_43

   点击Visual Studio 2008菜单Build-Build Solution,编译C#工程。在工程目录的bin\Debug目录下会生成ClassLibrary1.dll文件。

  把DLL文件注册到系统全局程序集缓存中

  

labview调用teststand例程 labview调用文件_库文件_44

图 4‑24 Microsoft .NET Framework 2.0 配置

  添加.Net控件

   新建CVI工程,在CVI中点击菜单Tools-Create .Net Controller…,添加生成的ClassLibrary1.dll文件,并添加生成的.fp文件的路径。点击确定之后,在CVI左下角的函数库窗口的Instruments文件夹下多出了ClassLibrary1库,在当前工程下多出了刚才指定的.fp文件。

  编写代码,编译运行

  

labview调用teststand例程 labview调用文件_库文件_45

labview调用teststand例程 labview调用文件_头文件_46

  

labview调用teststand例程 labview调用文件_头文件_47

图 4‑25 .Net程序运行结果

4.5 示例:CVI获取计算机CPU、硬盘、网卡ID

  

  

  

  

  

  获取CPU序列号(Intel)

  

表 4‑1 CPUID指令返回值与输入值对应关系表

labview调用teststand例程 labview调用文件_库文件_48

  

  获取网卡号

  

  

labview调用teststand例程 labview调用文件_头文件_49

  

  VC最终代码

  

  

labview调用teststand例程 labview调用文件_库文件_50

labview调用teststand例程 labview调用文件_库文件_51

labview调用teststand例程 labview调用文件_库文件_52

  

labview调用teststand例程 labview调用文件_库文件_53

  

  CVI调用DLL

  

labview调用teststand例程 labview调用文件_静态库_54

图 4‑26 CVI获取CPU、网卡序列号的工程目录

  

labview调用teststand例程 labview调用文件_库文件_55

  

  调试、运行

  

labview调用teststand例程 labview调用文件_库文件_56

图 4‑27 CVI获取CPU序列号、网卡物理地址运行结果

  

labview调用teststand例程 labview调用文件_头文件_57

图 4‑28 用Everest软件检测得到的CPU序列号与网卡物理地址

4.6 探索与实验