当前位置:首页 >> 信息与通信 >>

LABVIEW调用动态链接库


该文档版权归上海微视泰科工作室所有,转载请注明出处! 网址:http://www.microvt.com Email: hightechyoung@yahoo.com 作者:HighTech Young

6.3. 调用动态链接库(DLL)
相对于 CIN 来讲,NI 更推荐用户使用 DLL 来共享基于文本编程语言开发的代码。除了共享或重复利用 代码

,开发人员还能利用 DLL 封装软件的功能模块,以便这些模块能被不同开发工具利用。在 LabVIEW 中 使用 DLL 一般有以下几种途径: 1. 使用自己开发 DLL 中的函数。 2. 调用操作系统或硬件驱动供应商提供的 API。 对于前一种方法来说,又可以通过以下几步来实现: a) 在 LabVIEW 中定义 DLL 原型; b) 生成.C 或.C++文件,完成实现函数功能的代码并为函数添加 DLL 导出声明; c) 通过外部 IDE(如 VC++)创建 DLL 项目并编译生成.dll 文件。 d) 在 LabVIEW 项目中使用 DLL 中的函数。 以下章节将通过实例对这两种情况详细进行叙述。 6.3.1. 配置 Call Library Function Node(CFN) 无论在 LabVIEW 中使用自己开发的 DLL,硬件驱动供应商或者操作系统提供的 API,都可以通过 配置 Call Library Function Node (CFN,图 6-12)来完成。

图 6-12 LabVIEW 的 Call Library Function Node

在 CFN 图标的右键菜单上选择 Configure…” “ 打开 Call Library Function 配置对话框(图 6-13)。 通过该对话框,可以指定动态库存放路径、调用的函数名以及传递给函数的参数类型和函数返回值的类 型。在配置完后,CLF 节点会根据用户的配置自动更新其显示。 通过 Browse 按钮或者直接在“Library Name or Path”输入框中指定调用函数多在.dll 文件的路 径。 通过 Browse 按钮下的控件用户可以指定多个线程同时调用 DLL。 默认情况下, LabVIEW 以 Run “
11

该文档版权归上海微视泰科工作室所有,转载请注明出处! 网址:http://www.microvt.com Email: hightechyoung@yahoo.com 作者:HighTech Young in UI Thread ”方式调用 DLL,调用的函数将直接在用户线程中运行。另外一种方式为递归方式

“Reentrant” ,在这种情况下可以允许多个线程同时调用 DLL 中的函数。但要确保正常调用,必须使 DLL 中的代码线程安全。以下是一些最基本的线程安全特性: a. 代码不含有未受保护的全局数据(如全局变量,文件) ; b. 代码不访问硬件(即不含有寄存器一级的代码) ; c. 代码不调用非线程安全的函数、DLL 或者驱动; d. 代码使用信号量或者互斥量来保护全局量; e. 代码被一个非递归的 VI 调用时为线程安全。

图 6-13 CLF 配置对话框

在“Function Name”输入框中指定要调用函数的函数名。 通过“Call Conventions”下拉列表框指定调用 DLL 中函数的方式。可以指定调用方式为“C” (默认方 式) Windows 标准调用方式 stdcall”一般来说用 C” 或 “ 。 “ 方式调用开发人员自己写的 DLL 函数, “stdcall” 而 一般做为标准调用方式来调用 windows 的 API 通过 Parameter 域可以指定所调用函数的返回值类型。默认情况下 CFN 节点没有输入参数而且只有一 个 void 类型的返回参数。该参数由 CFN 节点第一对连接点的右端返回,代表 CFN 执行结果。如果返回参数 的类型是 void 类型,则 CFN 连接点为未启用状态(保持为灰色) 。CFN 的每一对连接点代表一个输入或输 出参数,若要传递参数给 CFN 则将参数连接至相应连接点的左端,若要读取返回值,则将相应连接点的右端 连接到 Indicator。 CFN 返回参数的类型可以是 Void,Numeric 或 String。只能为返回参数指定 Void 类型,输入参数不能 指定为 Void 类型。调用的函数没有返回值时,指定 CFN 的返回参数类型为 void 类型。即使参数有确定类 型的返回值,也可以指定 CFN 的返回类型为 Void,但是此时,函数的返回值将被忽略。 有些时候,调用的函数返回值不是以上三种类型,可以使用与以上三种类中有相同大小的一个来代替。 例如如果调用的函数返回一个 Char 类型数据, 则可以用一个 8-bit unsigned integer 的 Numeric 类型来代 替。此外,由于 LabVIEW 中没有指针,因此调用 DLL 中的返回指针的函数似乎不可能。但是可以设定返回 值类型为一个与指针有相同大小的 Integer 类型,LabVIEW 将把地址以整型值来看待,并且用户可以在以 后的调用中直接使用它。
12

该文档版权归上海微视泰科工作室所有,转载请注明出处! 网址:http://www.microvt.com Email: hightechyoung@yahoo.com 作者:HighTech Young

通过 Parameter 域和其右边的“Add a Parameter Before”, “Add a Parameter After” 和“Delete this Parameter”三个按钮可以增加、删除以及修改 CFN 的输入参数和类型。当用户选择某参数的类型后,其详 细的数据类型列表和参数传递方式列表将显示出来,以方便进行详细设定。表 6-1 列出了可以设定的输入参 数类型及其详细数据类型信息。
参数类型 说明 Numeric 型参数有以下几种数据类型: 8、16、32 和 64 位符号和无符号整型(Signed or Unsigned Integer) Numeric 4 字节单精度类型(4-byte single) 8 字节双精度类型(8-byte Double) 利用“Pass”下拉列表指定传递参数指针或是传递参数的指针。 Array 型参数的数据类型同 Numeric 型参数的数据类型; 通过 Dimensions 指定数组的维数; Array Format 有以下几种选项: Array Array Data Pointer 传递一维指针到数组值 Array handle 传递一个指向数组每一维的 4 个字节指针的指针, 其后为数组 的值 array handle Pointer 为数组的句柄传递一个指针 用 String Format 下拉列表框选择字符串类型 C String Pointer—以 null 字符结束的字符串 String Pascal String Pointer—附加长度字节的字符串 string handle—一个指向 4 个字节长度信息指针,其后为字符串的值。 string handle Pointer Waveform 类型的参数默认类型为 8-byte double,因此一般没有必要为其指定数据 Waveform 类型。但是必须为其指定维数,如果参数为单独的 Waveform,则指定 Dimensions 为 0,如果参数为 waveform 数组,则指定 Dimensions 为 1。 注意:LabVIEW 不支持超过 1D 的 waveform 数组! Digital Waveform Digital Data 如果参数为 digital waveform 数组,则指定 Dimensions 为 1,否则为 0。 注意:LabVIEW 不支持超过 1D 的 waveform 数组! 如果参数为 digital data 数组,则指定 Dimensions 为 1,否则为 0。 注意:LabVIEW 不支持超过 1D 的 digital Data 数组! Data Type 下拉列表框有以下选择: ActiveX Variant Pointer 传递一个指向 ActiveX 数据的指针 ActiveX IDispatch* Pointer 传递一个指向 ActiveX 自动化服务器 IDispatch 接口的 指针 IUnknown Pointer 传递一个指向 ActiveX 自动化服务器 IUnknown 接口的 指针 Adapt to Type 用来传递 LabVIEW 独有的数据类型给 DLL。 表 6-2 CFN 输入参数的类型

有时可能在 CFN 配置对话框中并不能找到要传递给它的参数类型, 在这种情况下可以通过下面方法来解 决。如果参数不含指针,则可以通过 Flatten to String 函数( )将参数转换为字符串,并将此字符串指

针传递给函数。还有其它一些技巧请参见 NI 手册。 设定后的最终结果显示在“Function Prototype”文本框中,在确认前,可以在此检查设定是否正确。 如果不正确可以在此修改设定。
13

该文档版权归上海微视泰科工作室所有,转载请注明出处! 网址:http://www.microvt.com Email: hightechyoung@yahoo.com 作者:HighTech Young

6.3.2. 调用自己开发 DLL 中的函数 开发人员可以在 LabVIEW 中指定 DLL 函数的原型, 然后在外部 IDE 中完成代码并编译生成.dll 文件以 供项目使用。 下面就以一个简单的求数组求和的项目为例来说明这种开发过程。 1. 在 LabVIEW 中创建 DLL 函数原型。 a) 在 LabVIEW 的 diagram 面板上添加一个 CFN 并通过其右键菜单打开 CFN 的配置对话框; b) 使“Library Name or Path”输入框为空; c) 指定函数名“Function Name”和调用方式“Calling Conventions”分别为 add_num 和 C; d) 重命名返回参数的名称为“error” ,并指定其类型为 Numeric 的 Signed 32-bit Integer; e) 用“Add a Parameter After”按钮添加第一个参数 p,指定其类型为 Array 的 4-byte Single 并 设定 Array Format 为 Array Data Pointer; f) 用“Add a Parameter After”按钮添加第二个参数 size,指定其类型为为 Numeric 的 Signed 32-bit Integer 并设置参数传递方式为 Value; g) 用“Add a Parameter After”按钮添加第三个参数 sum,指定其类型为为 Numeric 的 4-byte Single 并设置参数传递方式为 Pointer to Value; h) 至此,函数的原型应如下所示(图 6-14) :
long add_num(float *p, long size, float *sum);

图 6-14 CFN 的配置结果

i) 确定后会发现 CFN 根据配置自动进行了更新更新后的情况如右图示。 2. 生成.C 或.C++文件,完成实现函数功能的代码并为函数添加 DLL 导出声明; 在 CFN 节点上通过右键菜单选择“Create .C File…”生成 mydll.c 文件,其内容如下:
/* Call Library source file */ 14

该文档版权归上海微视泰科工作室所有,转载请注明出处! 网址:http://www.microvt.com Email: hightechyoung@yahoo.com 作者:HighTech Young #include "extcode.h" long add_num(float p[], long size, float *sum); long add_num(float p[], long size, float *sum) { /* Insert code here */ }

将以下代码插入到/* Insert code here */句之后实现函数的功能。
int i; float tmpSum = 0; if(p != NULL) { for(i=0; i < size; i++) tmpSum = tmpSum + p[i]; } else return (1); * sum = tmpSum; return (0);

在完成实现函数功能的代码后,还必须为函数添加导出声明以便能在 LabVIEW 中使用这些函数。 C/C++声名导出函数的关键字是_declspec (dllexport),使用该关键字可以代替模块定义文件。 对于此处的例子来说,只要在函数声明和定义部分添加关键字即可。最终代码如下:
/* Call Library source file */ #include "extcode.h" _declspec (dllexport) long add_num(float p[], long size, float *sum); _declspec (dllexport) long add_num(float p[], long size, float *sum) { /* Insert code here */ int i; float tmpSum = 0; if(p != NULL) { for(i=0; i < size; i++) tmpSum = tmpSum + p[i]; } else return (1); * sum = tmpSum; return (0); }

3. 在外部 IDE(以 VC++为例)中创建 DLL 项目并编译生成.dll 文件。 用 VC++ 6.0 进行编译生成.dll 文件的步骤如下: a) 在 VC++ 中 创 建 一 个 DLL 项 目 , 如 果 在 DLL 中 没 有 使 用 MFC 就 选 择 创 建 “ Win32
15

该文档版权归上海微视泰科工作室所有,转载请注明出处! 网址:http://www.microvt.com Email: hightechyoung@yahoo.com 作者:HighTech Young Dynamic-Link Library” ,否则选择“MFC AppWizard(dll)” ,对此例子来说选择前者。选定后

进入下一步选择创建一个空的 DLL 项目。 b) 通过 ProjectAdd to ProjectFiles 添加 mydll.c 到创建的 mydll 项目之中 c) 通过 ProjectSettings 打开项目配置对话框,选择 C/C++选项卡。 d) 配置项目的 All Configurations。选择 Settings For 下拉列表框中的 All Configurations,选择 Category 下拉列表框中的 Code Generation, 最后设置 Struct member alignment 为 1 Byte。 配置结果如图 6-15。

图 6-15 配置项目的 All Configurations

e) 配置项目的 Release 版本。 选择 Settings For 下拉列表框中的 Win32 Release, 选择 Category 下拉列表框中的 Code Generation,最后从 Use run-time library 下拉列表框中选择 Multithreaded DLL。配置结果如图 6-16。 f) 配置项目的 Debug 版本。选择 Settings For 下拉列表框中的 Win32 Debug,选择 Category 下拉列表框中的 Code Generation,最后从 Use run-time library 下拉列表框中选择 Debug Multithreaded DLL。配置结果如图 6-17。

16

该文档版权归上海微视泰科工作室所有,转载请注明出处! 网址:http://www.microvt.com Email: hightechyoung@yahoo.com 作者:HighTech Young

图 6-16 配置项目的 Release 版本

图 6-17 配置项目的 Debug 版本

17

该文档版权归上海微视泰科工作室所有,转载请注明出处! 网址:http://www.microvt.com Email: hightechyoung@yahoo.com 作者:HighTech Young

4. 在 LabVIEW 项目中调用.dll 中的函数。 创建如图 6-18 所示的 VI,其中 Array 为 RepresentationSingle Precision 类型的数组,Sum 为 RepresentationSingle Precision 类 型 的 Indicator, error 为 RepresentationLong 类 型 的 Indicator。运行后可以看到对数组求和的结果。

图 6-18 调用 DLL 中函数的 VI

6.3.3. 调用 Win32 API 在 LabVIEW 可以通过 CFN 调用 Win32 API 或者是硬件驱动供应商提供的驱动程序。通过调用这些函 数用户能利用与操作系统进行交互或者利用第三方供应商提供的函数来扩展自己项目的功能。以下章节以调 用 Win32 API 中 MessageBox 函数来实现一个同时带 Abort, Retry, Ignore 按钮和一个警告图标的消息对 话框为例,叙述在 LabVIEW 中利用 CFN 调用 Win32 API 的方法。 要在 LabVIEW 项目中调用 Win32 API, 首先要从 Microsoft 提供的相关开发文档中找到所要调用 API 函数的原型和其所在.dll 文件的名字。要查找这些信息,可以参考 Microsoft Software Development Kit (SDK)或 MSDN 的相关文档。从文档中找到 MessageBox 函数的原型和相关的一些信息如下。
int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType); ----Requirements:---Windows: Requires Windows 98 or later. Windows CE: Requires version 1.0 or later. Header: Declared in winuser.h. Import Library: Use user32.lib. Unicode: Implemented as Unicode and ANSI versions on Windows. // 父窗口的句柄 // 消息窗中显示的文本 // 消息窗的标题 // 消息窗的类型

找到这些信息后,就可以进行调用API函数的的第二步:将参数类型映射为LabVIEW支持的数据类型。 Win32 API函数用了多种非标准C的数据类型,这给在LabVIEW中调用API带来了一点麻烦。但是幸运的是, API函数所用的这些非标准数据类型只仅仅是标准C数据类型的别名。例如上面例子中MessageBox函数使用 的参数类型与标准C的参数类型有以下映射关系:
HWND LPCTSTR = = int * * const char * 18

该文档版权归上海微视泰科工作室所有,转载请注明出处! 网址:http://www.microvt.com Email: hightechyoung@yahoo.com 作者:HighTech Young UINT = unsigned int

可直接将LPCTSTR和UINT映射为LabVIEW支持的类型。LPCTSTR与C语言字符串等价,UINT等价于 LabVIEW的U32数据类型。但是映射HWND稍微有点麻烦。HWND是指向整型数指针的指针。观察 MessageBox函数中HWND的作用,可以看出此参数只仅仅用来标识消息窗父窗口的句柄,因此,我们没有 必要知道句柄本身的值,而只要关注HWND参数本身,由于HWND是指向整型数指针的指针,因此可以将它 看作32位无符号整型量(U32) 。在Windows SDK中有很多以H开头的量(句柄) ,一般说来,在开发过程 中,都可以将它看作32位无符号整型量(U32)而不必关心它本身的值。如果不能确定API函数参数数据类 型所对应的标准C语言数据类型,可以在头文件windef.h中查找相应的#define或typedef定义。 有了这些等价转换,还要关注API函数中常量与LabVIEW中数据类型或表示方法的映射。在Visual Studio中,编程人员一般不直接使用常量的值,而是使用与预定义的常量名,但是在LabVIEW中却必须使 用实际的值。例如对于MessageBox函数来说,代表消息窗类型的参数uType可以使用下表中几个常量。
常量 MB_ABORTRETRYIGNORE MB_CANCELTRYCONTINUE MB_HELP MB_OK MB_ICONWARNING 说明 带有Abort, Retry, Ignore按钮的消息窗 Win2000上可替代MB_ABORTRETRYIGNORE量,具有Cancel, Try Again, Continue按钮的消息窗 Win2K/XP上为消息窗添加Help按钮并在用户按下此按钮时发送 WM_HELP消息给父窗口的的消息窗 默认值只有一个OK按钮的消息窗 带有警告图标的消息窗

通过在SDK文档中查找到的信息(Header: Declared in winuser.h.)知道这些常量在头文件winuser.h中
有定义。通过该头文件可以找到相关定义如下。 … #ifdef UNICODE #define MessageBox MessageBoxW #else #define MessageBox MessageBoxA #endif ... #define #define #define #define … MB_OK MB_ABORTRETRYIGNORE MB_ICONWARNING MB_ICONEXCLAMATION 0x00000000L 0x00000002L MB_ICONEXCLAMATION 0x00000030L

在SDK文档中,常量通常取位域中的某一位作为其值。位域是通常是指一个每一位控制某种属性的单个 整型量。通过或运算(|)可以将多个常量组合起来达到多种需要的效果。从逻辑运算角度来讲,进行或运算 等价于选择了位域中的多个控制位。例如可以通将MB_ABORTRETRYIGNORE和MB_ICONEXCLAMATION 进行或运算后的值传给uType可以创建一个同时带Abort, Retry, Ignore和一个警告图标的消息窗。 MB_ABORTRETRYIGNORE的值为0x02, MB_ICONEXCLAMATION的值为0x30,经过或运算后的值为 0x32。在Visual Studio开发中可以直接将“MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION”常 量或运算表达式作为参数uType传递给MessageBox函数来实现一个同时带Abort, Retry, Ignore按钮和一 个警告图标的消息对话框,但是LabVIEW却不支持这种形式的参数传递。因此必须将常量表达式转换为 LabVIEW支持的形式。这可以通过表达式 来实现。注意其中数字均为十六进制数。 最后还要根据开发项目是ANSI项目还是Unicode项目,并参照SDK文档选择合适的函数。一般来说大 多数LabVIEW项目均为ANSI项目,因为大多数LabVIEW的字符串均为ANSI标准字符串。对于此处的例子
19

该文档版权归上海微视泰科工作室所有,转载请注明出处! 网址:http://www.microvt.com Email: hightechyoung@yahoo.com 作者:HighTech Young

来说,通过参看从SDK文档中获取的信息可知MessageBox函数有ANSI和Unicode两种实现(Unicode: Implemented as Unicode and ANSI versions on Windows.)。查看头文件winuser.h中内容(参见上页表)可 知对于ANSI类型的项目应选择函数名MessageBoxA。实际上在库文件user32.dll(在windows中相对于静 态库文件一般都存在一个同名的动态库文件)中,只存在函数MessageBoxA和MessageBoxW并没有 MessageBox函数的实体。 综上所述,要调用API实现一个同时带Abort, Retry, Ignore按钮和一个警告图标的消息对话框可对CFN 节点完成如图6-19所示的配置。

图 6-19 CFN 节点的配置

完成后VI的后面板和运行结果可能如图6-20所示。

图 6-20 VI 的后面板和运行结果

20


相关文章:
Labview调用C#生成的动态链接库
Labview调用C#生成的动态链接库_计算机软件及应用_IT/计算机_专业资料。1. 打开 VS2010,新建->类库并输入以下程序 2. 右键点击右侧的项目名称(ClassLibrary1) 3....
如何从LabVIEW调用动态链接库DLL
如何从 LabVIEW 调用动态链接库 DLL 主要软件: 主要软件版本:1.0 主要软件修正版本:N/A 次要软件:N/A 问题:如何从 LabVIEW 中调用动态链接库 DLL 解答:要从...
Labview调用dll动态链接库总结
如何在LabVIEW使用动态... 10页 免费L​a​b​v​i​e​w​调​用​d​l​l​动​态​链​接​库​总​结 暂无评价|0人...
74.调用动态链接库 6 - LabVIEW 中对 C 语言指针的处理
调用动态链接库 6 - LabVIEW 中对 C 语言指针的处理 C 语言函数常有指针类型的参数,有时候,在 LabVIEW 中只能得到一个 指向某个数据的指针。比如,在第4节里...
在LabVIEW中调用VC++生成的动态链接库文件DLL
LabVIEW调用VC++生成的动态链接库文件DLL_IT/计算机_专业资料。在LabVIEW调用VC++生成的动态链接库文件DLL的具体方法。VC++生成的 LabVIEW调用 VC++...
LabVIEW外部调用DLL
LabVIEW 与外部程序间 DLL 文件的调用什么是 DLL 文件 DLL(动态链接库)文件是 Dynamic Link Library 的缩写形式,是一种允许程序共享执行特殊任务所 必需的代码和...
LabVIEW如何方便地调用DLL文件
选择了 Run in any thread 方式,LabVIEW 会在最方便的线程内运行动态链接库函数,且一般会与调用它的 VI 在同一个线程内运行。因为 LabVIEW 是自动多线程的语言...
71.调用动态链接库 3 - 简单数据类型参数的设置
调用动态链接库 3 - 简单数据类型参数的设置 复杂问题先从简单地说起,在 DLL 和 LabVIEW 之间传递参数,最常用的三种数据类 型是:数值类型,字符串,数值型数组....
Labview DLL调用指南-非常有用
Labview DLL调用指南-非常有用_计算机软件及应用_IT/计算机_专业资料。【转】 ...2)使用动态链接库的好处 动态链接库通常不能直接运行,也不能接收消息。它们是...
动态链接库在LabVIEW中的高级应用
动态链接库LabVIEW中的高级应用_调查/报告_表格/模板_实用文档。动态链接库LabVIEW中的高级应用 摘要:LabVIEW 中的提供了调用共享库函数的接口,但是一些现成的...
更多相关标签:
labview动态链接库 | js调用dll动态链接库 | java调用动态链接库 | c 调用动态链接库 | 调用动态链接库 | vc 调用qt动态链接库 | matlab调用动态链接库 | qt调用动态链接库 |