虚拟仪器开发平台调用外部DLL文件简介

虚拟仪器开发平台主要包括基于图形化编程语言的LabVIEW和基于文本式编程语言的LaWindows/CVI,LaWindows/CVI跟传统的编程语言(比如C)很相似。
LabWindows/CVI 是National Instruments 公司(美国国家仪器公司,简称NI 公司)推出的交互式C 语言开发平台。LabWindows/CVI 将功能强大、使用灵活的C 语言平台与用于数据采集分析和显示的测控专业工具有机地结合起来,利用它的集成化开发环境、交互式编程方法、函数面板和丰富的库函数大大增强了C 语言的功能,为熟悉C 语言的开发设计人员编写检测系统、自动测试环境、数据采集系统、过程监控系统等应用软件提供了一个理想的软件开发环境。与NI公司开发的另一个虚拟仪器开发工具LabVIEW相比,其更适合中、大型复杂测试软件的开发。
LabVIEW是一种程序开发环境,由美国国家仪器(NI)公司研制开发,类似于C和BASIC开发环境,但是LabVIEW与其他计算机语言的显著区别是:其他计算机语言都是采用基于文本的语言产生代码,而LabVIEW使用的是图形化编辑语言G编写程序,产生的程序是框图的形式。
而动态链接库(Dynamic Link Library 或者 Dynamic-link Library,缩写为 DLL),是微软公司在微软Windows操作系统中,实现共享函数库概念的一种方式。 动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。DLL 有助于共享数据和资源。
LaWindows/CVI显式调用DLL文件
LaWindows/CVI可以通过多种方法调用外部dll文件,如通过“Create ActiveX Controller”或者“Create .NET Controller”等。但并不是都有效,但是LoadLibrary方法却是一个不错的方法。这种方法的一个好处是动态加载,在需要的地方加载,用完就释放掉。缺点是要知道dll中的函数原型。
1.动态载入 DLL
动态载入DLL方式是指在编译之前并不知道将会调用哪些 DLL 函数,完全是在运行过程中根据需要决定应调用哪些函数。
方法是:用 LoadLibrary 函数加载动态链接库到内存,用 GetProcAddress函数动态获得 DLL 函数的入口地址。当一个 DLL 文件用 LoadLibrary 显式加载后,在任何时刻均可以通过调用 FreeLibrary 函数显式地从内存中把它给卸载。
动态调用DLL使用的 Windows API 函数主要有3 个,分别是 LoadLibrary、 GetProcAddress 和FreeLibrary。
2.三个函数的功能说明
1.LoadLibrary 函数
[格式]:function LoadLibrary(LibFileName : PChar): Thandle;
[功能]:加载由参数 LibFileName 指定的 DLL 文件。
[说明]:参数 LibFileName 指定了要装载的 DLL 文件名,如果 LibFileName 没有包含一个路径,系统将按照:当前目录、Windows 目录、Windows 系统目录、包含当前任务可执行文件的目录、列在 PATH 环境变量中的目录等顺序查找文件。如果函数操作成功,将返回装载 DLL 库模块的实例句柄,否则,将返回一个错误代码。
2.GetProcAddress 函数
[格式]:function GetProcAddress(Module:Thandle; ProcName:PChar): TfarProc;
[功能]:返回参数 Module 指定的模块中,由参数 ProcName 指定的过程或函数的入口地址。
[说明]:参数 Module 是包含被调用函数的 DLL 句柄,这个值由 LoadLibrary 返回,ProcName是指向含有函数名的以null结尾的字符串指针,或者可以是函数的次序值,但大多数情况下,用函数名是一种更稳妥的选择。如果该函数执行成功,则返回 DLL 中由参数 ProcName 指定的过程或函数的入口地址,否则返回 null 。
3.FreeLibrary 函数
[格式]:procedure FreeLibrary(Module: Thandle);
[功能]:将由参数 Module 指定的 DLL 文件从内存中卸载 1 次。
[说明]:Module 为 DLL 库的句柄。这个值由 LoadLibrary 返回。由于 DLL 在内存中只装载一次,因此调用 FreeLibrary 首先使 DLL 的引用计数减 1,如果计数减为 0 则卸载该 DLL。
3.实际应用
通过LaWindows/CVI构建的一个简单计算器程序为例,在工程文件中添加一个dll文件FreeMem.dll,FreeMem.dll用于释放内存,无入口参数。通过调用FreeMem.dll文件来释放内存,函数原型如下:void FreeMem(void );,构建的示例计算器程序的头文件如下:
#include <windows.h>
#include <formatio.h>
#include <ansi_c.h>
#include <cvirte.h>
#include <userint.h>
#include "CAL.h"
注意:#include <windows.h>是必须添加的,因为我们需要WINDOWS的API函数。
我们需要定义以下函数和变量:
typedef void (*FreeMem)(void);
FreeMem fl=NULL;
HINSTANCE hDll;

在要进行调用dll文件的程序模块中添加以下代码;

运行效果如下:

因为本程序比较小,不怎么耗内存,因此清除内存的效果表面上无法观察,但是通过对话框提示可以看出,FreeMem.dll文件调用成功,如果工程文件中缺失FreeMem.dll的话,程序则会提示调用函数 FreeMem失败。

如果dll文件中的函数原型如下:
Char *function(const char *s1,const char *s2);
则函数及变量定义如下:
Typedef char* (*function)( const char * ,const char * );
function fl=NULL;
HINSTANCE hDll;
通过以上实例可以看出,LaWindows/CVI通过LoadLibrary方法调用外部dll文件是一个不错的选择。
LabVIEW调用外部DLL
为了在LabVIEW中能够调用其他语言编写的程序,其提供了强大的外部程序接口能力,这些接口包括DLL、C语言接口(CIN)、 ActiveX、NET. DDE、MATLAB等。通过DLL,用户能够方便地调用C、VC、VB等编程语言编写的程序。而LabVIEW 中是通过Call Library Function Node(CLN)节点来完成DLL文件调用的。
本文通过LabVIEW构建计算器程序为例进行简单的介绍。以前面提到的FreeMem.dll文件为例,在程序框图放入Call Library Function Node,双击弹出对话框,在Function页面的Library name or path中输入已知的的FreeMem.dll文件路径,Function name选择FreeMem,其他选项默认。

如果是LabVIEW生成的DLL文件,在Parameters页面不需要做改动,但是由于VI还有一路输出,所以还需要添加一个参数y,作为DLL文件的输出。

如果是C语言等非LabVIEW生成的DLL函数,需要将return type的type选项和Data type选项改成函数定义的参数类型,对于函数里输入的参数也都需要自行添加。Callbacks和Error Checking则不需要改动。

运行效果如下:

因为本程序比较小,几乎不消耗内存,因此清除内存的效果表面上无法观察,但是通过对话框提示可以看出,dll文件调用成功,如果FreeMem.dll文件的路径发生改变的话,程序则会提示dll文件调用失败。
所以,使用LabVIEW也可以方便地调用各种编译软件生成的DLL文件。这样,用户在编写大型项目时更加灵活,也为熟悉C语言的工程师提供了巨大的方便。
总结
LabVIEW相对LabWindows/ CVI比较方便上手,适合不太熟练文本编程使用,LabWindows /CVI是以标准C为基础编程语言的一种开发工具,界面和一些基本使用都很象VC,功能相对强大,但是使用起来比LABVIEW要复杂的多。
但是两者不仅可以方便地调用各种编译软件生成的DLL文件,自己也能生成DLL文件供其他编译软件调用。这样,用户在编写大型项目时更加灵活,也为熟悉C语言的工程师提供了巨大的方便。本文只对LabVIEW和LabWindows/ CVI调用DLL文件做了一些简单的介绍,很多高级功能和技巧,读者可以在实际运用中逐渐掌握。