LabVIEW与外部程序间DLL文件的调用
LabwindowsCVI调用外部DLL文件的问题

}
}
这样的目的是:在外部调用的时候,便于调用。
C源文件编写完整后,把相关的*.uir文件添加到工程中,然后编写一个*.h文件,命名为exampledll.h,里面包含一个源文件中的函数申明。定义如下:
externint InitUIForDLL (void);//调用面板的函数
InitUIForDLL ();
return 0;
}
(2)通过一个按键来调用dll,即在一个工程中通过一个按钮来调取dll中的函数,来完成此按扭的功能。
与用c源代码来调用的方式一样,只是此工程已经有*.uir对象面板,在*.uir的面板上添加一个按钮,为按钮生成一个函数,在函数中调用外部dll中的函数。在编译前,要将*.lib和*.dll文件和头文件包含在工程中,并且将dll中的函数用一个*.h头文件包含:
int __stdcall DllEntryPoint (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
这两个函数是DLL动态链接库必须包含的两个函数,函数的具体内容为:
#include <cvirte.h>
int __stdcall DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
#include "CFI.h"
static int panelHandle;
int main (int argc, char *argv[])
{
if (InitCVIRTE (0, argv, 0) == 0)
return -1;/* out of memory */
LabVIEW编程调用DLL时遇见的问题

LabVIEW编程调用DLL时遇见的问题对于使用LabVIEW编程的人来说,都知道LabVIEW功能强大,但也会发现似乎缺少某些功能,而像其他编程语言的DLL、ActiveX组件则能提供。
在使用DLL(动态链接库)时,最大的困难就是把函数参数的数据类型映射为相应的LabVIEW中的数据类型。
LabVIEW 提示:未定义符号可能会造成函数和参数无法被识别。
如要解决该问题,检查头文件并确定是否必须添加预定义符号。
单击上一步按钮返回至向导的前一页并添加预定义符号(例如,"NIAPI_stdcall = __stdcall"或"NIAPIDefined = 1")在一次进行串口调试软件的编写过程中,要求使用动态链接库(其实使用VISA同样可以实现),使用导入共享库工具以自动生成配置CLN(Call Library Function)节点,工具在“工具—导入—共享库(.dll)”菜单项下,专门用于将DLL 中函数包装成VI。
下一步下一步点击解析头文件后,依然遇见(如下图)extern UINT Recv(UCHAR *pRecvBytes,UINT unRecvLength);(函数原型)未定义符号可能会造成函数和参数无法被识别。
如要解决该问题,检查头文件并确定是否必须添加预定义符号。
单击上一步按钮返回至向导的前一页并添加预定义符号(例如,"NIAPI_stdcall = __stdcall"或"NIAPIDefined = 1")归咎原因就是头文件中的一些类型定义不符合标准C语法,而使解析器无法获得正确的的mPWIN32_COMMAND定义。
DLL函数的头文件中可能使用了某个系统定义的数据类型,数据类型的定义在windows.h中,(windows.h是Windows SDK的一个文件,VC等开发环境中常常带有Windows SDK),要正确解析必须得到这些数据类型,也就是找到windows.h 这个头文件,用户须把windows.h文件的全路径加在“包括路径”中。
关于LabVIEW产生的DLL被C调用的问题

关于LabVIEW产生的DLL被C调用的问题1 LabVIEW的工作1.1 工程项目从LV8.0开始,想要生成exe、安装程序或DLL就必须首先创建1个工程,然后把所有有关的VI全部添加到工程中,如图1:图1 LV项目为了使目录结构清晰,最好把最后需要输出的VI放置在一起,把子VI放置在一起,如图1中,虚拟目录Top Level Vis用来存放3个输出的VI(可以把它想像成DLL中的函数)、虚拟目录Dynamic Vis存放子VI、虚拟目录Support Files存放支持文件(位图、光标等)。
1.2 VI设置如同在LV中一样,有些VI完全是作为计算模块使用的(调用时不会弹出界面,如图1中的acquire.vi、analyze.vi),而有些是用来显示界面的(调用时弹出对话框,如图1中的present.vi)。
那么如何设置1个输出VI是否显示界面呢?想要产生界面调用的函数,请配置Window Appearance(如图2),然后确保红线圈住的地方必须被选中:图2 VI界面设置1.3 输出配置(Build Specification)右击Build Specification选择New->DLL,弹出DLL输出配置对话框,其有以下对话框需要配置:1.3.1 基本信息(Information)图3∙Build specification name—指定唯一的生成模板名称(出现在项目管理页面中),用以和其他模板相区别∙Target filename—指定输出的DLL名称∙Destination directory—指定生成文件的输出路径∙Build specification description—描述该生成模板的相关信息。
1.3.2 输出源指定(Source Files)图4∙Project Files窗口—显示项目窗口My Computer下列举的项目(如图1),使用图4中的左/右箭头可将My Computer下列举的项目移入/移出Exported VIs和Always Included窗口。
图解LABVIEW调用DLL

前言:LABVIEW是一个强大的图形编程语言,使用很简单,就是你没有任何编程经验也可以LABVIEW编程,对于需要快速上手图形编程的人是一个不错的选择。
在很多时候我们会用C语言写一些计算机的底层驱动,比如USB数据传输或者串口数据传输,如何把我们自己写的驱动程序集成到LABVIEW中呢?下面我就用图和简单说明的方式给大家说说,由于我也是初学,所以有的地方可能会有错误或不准确的地方,欢迎大家指正,废话不多说了,下面开始正式的教程。
目的:通过一个现成的I2C适配器控制I2C接口的AM2311温湿度传感器,将测得的温度和湿度用LABVIEW显示出来,最终效果如图所示。
准备:1、安装LABVIEW2010。
2、I2C适配器1台。
3、I2C适配器上位机驱动函数库,和函数库头文件。
4、AM2311传感器模块一台。
第一步:打开LABVIEW2010,按下图导入我们需要使用的DLL文件。
得到如下界面,点击下一步。
打开DLL和头文件,点击下一步。
到这里我们的库就基本上导入完毕,但是还有一件事情要做,因为在Ginkgo_Driver.dll里面用到了vt214x.dll里面的一些函数,所以要把这个文件拷贝到刚刚生成库的目录下,否则在运行程序的时候会出现找不到这个DLL的错误提示,而且程序也不能正常工作。
我生成的库目录是:D:\Program Files (x86)\National Instruments\LabVIEW 2010\user.lib\Ginkgo_Driver。
你可以根据自己的实际情况处理,拷贝这个文件后在这个目录下的文件如下图所示:到这里库基本上就导入完毕,下面我们就可以在VI程序里面使用这些库函数了。
第二步:打开LABVIEW软件,新建一个VI文件,另存名字为AM2311.vi。
我们在前面板设计为如下界面。
切换到程序款图界面,因为我们程序需要顺序执行,最后需要在一个循环里面循环读取数据,所以我们可以通过平铺顺序结构来设计程序,在平铺顺序结构的第一帧调用刚刚导入的VTIF_I2C_SelectDevice()函数选择设备,在第二帧调用VTIF_I2C_Init()初始化函数初始化I2C适配器,然后就可以循环的读取数据了,最好将数据解析出来并显示出来。
LabVIEW 调用 C-C++ Dll 详解

LabVIEW 调用C/C++ Dll 详解LabVIEW 在配上NI 的采集卡或者别的第三方的硬件,约等于神器(虽然有时候贵了点)。
这样你可以比较集中精力的专注于数据处理了,就不用学习麻烦的Win32 的GUI 编程, 也不用关注和你自己搞的采集板之间的通信了。
对于每一个测控行业的程序来说,基本上都是:初始化-->数据采集-->数据处理-->数据显示-->数据保存-->结束的一个过程。
当然如果是实时的,那么采集,处理,显示就是在一个loop 里面。
当然为了保证实时性,数据处理和数据采集不一定在一个线程里,因为处理的时候把采集给block 住也挺傻的。
LabVIEW 很容易帮你搞定:初始化-->数据采集-->数据处理-->数据显示-->数据保存-->结束但是数据处理部分,是和你的学科紧密相关的,有时候算法会诡异到你很难用VI来实现,那么你就要有C++”target=“_blank”>C++code来搞了。
那么C/C++ 是如何与LabVIEW 交互的呢,本文来较详细的阐述一下,因为准备采用总分总的写作手法...所以先来个概括...1. 把C/C++ code 编译成Dll。
2. 用LabVIEW 的call library node 来调用。
难点在于:如何把LabVIEW 的数据类型和C/C++ 的来对应。
控件x 相当与一个double,当然其类型也是可以选择的(如右图所示)。
boolean 按理说应该是一个bool, 但是传入call library node 的时候,一般要转成unsigned int 型。
cluster 其实就是个struct ,左图的cluster 是:struct tCluster{ double x11; // 类型都可以向右图那样自己配置double x2; int x3;};对于string,这里要着重讲一下,labview 的string 类型里面是包含长度信息的,它不是一个简单的char *它是个LStrHandle 类型:定义咋extcode.h 里面(可以在labview 目录下搜到)typedef struct {int32 cnt;uChar str[1];} LStr, *LStrPtr, **LStrHandle;cnt 就是含有多少个字符,str 这个指针所指的就是数据区的第一个字符。
LABVIEW的DLL与API调用

LABVIEW的DLL与API调用LABVIEW的DLL与API调用一.实验目的1.熟悉LabVIEW调用动态链接库的过程2.学会编写用LabVIEW调用WINDOWS的API函数二.实验器材1.计算机(带有声卡)2.LABVIEW8.20软件三.实验原理在开发自动测量系统时,经常遇到计算机与仪器的通信问题,涉及仪器控制及数据处理问题,LabVIEW语言在这一领域的应用有着独到的优势。
为了在LabVIEW中能够充分利用其他编程语言的优势,LabVIEW提供了外部程序接口能力,包括动态链接库(DLL)、C语言接口(CIN)、ActiveX和Matlab等。
动态链接库是基于Windows程序设计的一个非常重要的组成部分。
LabVIEW 开发中使用DLL,可以使代码更简洁,内存资源的使用更经济,而且可以便捷地利用仪器厂商或第三方提供的仪器控制子程序加速开发进程。
而windows平台包含有大量的API函数,这些API函数提供了大量在Windows环境下可操作的功能,它们位于Windows系统目录下的多个DLL文件中,因此在LabView中调用API 函数和DLL的方法是一致的。
在LabVIEW中,利用库函数节点可以较容易地实现对DLL的调用,从而提高了程序的开发效率。
使用调用库函数节点,可以调用Windows标准的动态连接库,也可以调用用户自己编制的DLL。
LabView中动态链接库的调用可在程序框图的函数选板中选取“调用库函数节点”来完成,该节点位于:互连接口->库和可执行程序->调用库函数节点。
将选择好的调用库函数节点图标放在程序框图中,然后通过对它的节点图标进行配置,可以指定DLL模块中与LabVIEW数据交换的相应的驱动函数。
在调用DLL时,首先要找到找到头文件(*.h)或者函数原型声明,确定你需要调用的函数,注意函数的参数是否包含了原始数据类型参数比如int,char, double,等等或者是否包含了复杂数据类型比如clusters。
labview调用dll方法+

0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
unsigned char i;
unsigned char RH = 0xff;
unsigned char RL = 0xff;
unsigned char *buf=(unsigned char *)pbuf;
do
{
i = *buf ^ RL;
buf ++;
RL = RH ^ CRC_TABLE_H[i];
RH = CRC_TABLE_L[i];
}while(--len);
return(RH * 256 + RL);
}
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
};
/*******************************************************************************
LabVIEW与外部程序间DLL文件的调用

图20 Parameters页面点击“OK”,将生成的CLN的输入段连接到DAQmx Read.vi,return type 输出连接到波形图表上,即可实现采集值放大10倍的功能。
图21 完成后的程序方法二LabVIEW中还有一种方法可以调用DLL文件,在VI的选项栏,依次选择Tools——Import——Shared Library(.dll),弹出Import Shared Library 对话框。
图22 生成Import Shared Library对话框选择Create VIs for a shared library,点击Next,在Shared Library (.dll) Files中输入Scale.dll文件的路径,Head(.h) File里填写头文件的路径。
图23 选择DLL文件路径和头文件路径点击Next,如果DLL文件中依赖其他的一些DLL文件,需要在Include Paths中填写这些文件的路径。
其他选项可以根据客户需求设置,一般默认即可。
这样一直点击Next到最后,选择Open the generated library,点击Finish。
这样可以生成一个.lvlib格式的库文件,里面包含了Scale.vi,这是将调用该DLL 文件的方法封装好的VI,只留下输入和输出接口,方便运用到LabVIEW的程序中。
直接将Scale.vi拖放到刚才的连续采集中即可完成方法一的功能。
图24 完成的程序VC调用LabVIEW生成的DLL文件刚才介绍了LabVIEW调用DLL文件的方法,使用VC调用LabVIEW生成的DLL 文件也很简单。
还是以之前生成Scale 的DLL文件为例,不同的是采集电压程序使用的是C语言的例程,但和LavVIEW实现的功能相同。
首先将先前生成Scale DLL文件时,路径下所有的文件全部复制粘帖到C语言例程的文件夹下。
打开连续采集程序,点击状态栏的Project——Settings,在Project Settings对话框中加载入Scale.lib的静态链接库。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
LabVIEW与外部程序间DLL文件的调用什么是DLL文件DLL(动态链接库)文件是Dynamic Link Library的缩写形式,是一种允许程序共享执行特殊任务所必需的代码和其他资源的可执行文件。
其多数情况下是带有DLL扩展名的文件,但也可能是EXE或其他扩展名。
Windows提供的DLL文件中包含了允许基于Windows 的程序在Windows环境下操作的许多函数和资源。
动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。
这些函数的可执行代码位于一个DLL中,该DLL包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。
DLL还有助于共享数据和资源,多个应用程序可同时访问内存中单DLL副本的内容。
总之,DLL是一个包含可由多个程序同时使用的代码和数据的库。
动态链接是相对于静态链接而言的。
所谓静态链接是指把要调用的函数或者过程链接到可执行文件中,成为可执行文件的一部分。
换句话说,函数和过程的代码就在程序的exe文件中,该文件包含了运行时所需的全部代码。
当多个程序都调用相同函数时,内存中就会存在这个函数的多个拷贝,这样就浪费了宝贵的内存资源。
而动态链接所调用的函数代码并没有被拷贝到应用程序的可执行文件中去,而是仅仅在其中加入了所调用函数的描述信息(往往是一些重定位信息)。
仅当应用程序被装入内存开始运行时,在Windows的管理下,才在应用程序与相应的DLL之间建立链接关系。
当要执行所调用DLL中的函数时,根据链接产生的重定位信息,Windows才转去执行DLL中相应的函数代码。
由于向运行于Windows操作系统下的程序提供代码、数据或函数,程序可根据DLL文件中的指令打开、启用、查询、禁用和关闭驱动程序。
在Windows操作系统中,DLL对于程序执行是非常重要的, 因为程序在执行的时候, 必须链接到DLL文件, 才能够正确地运行。
而有些DLL文件可以被许多程序共用,因此程序设计人员可以利用DLL文件, 使程序不至于太过巨大。
但是当安装的程序越来越多,DLL文件也就会越来越多, 如果当删除程序的时候, 没有用的DLL文件没有被删除的话, 久而久之就造成系统的负担了。
通过使用DLL,程序可以实现模块化,由相对独立的组件组成。
因为模块是彼此独立的,所以程序的加载速度更快,而且模块只在相应的功能被请求时才加载。
此外,可以更为容易地将更新应用于各个模块,而不会影响该程序的其他部分。
例如,可能有一个工资计算程序,税率每年都会更改,当这些更改被隔离到DLL中以后,我们无需重新生成或安装整个程序就可以应用更新。
总的来说,使用DLL文件有以下好处:1、多个应用程序可以共享代码和数据。
比如Office软件的各个组成部分有相似的外观和功能,这就是通过共享动态链接库实现的。
2、在钩子程序过滤系统消息时必须使用动态链接库。
3、动态链接库以一种自然的方式将一个大的应用程序划分为几个小的模块,有利于小组内部成员的分工与合作,而且各个模块可以独立升级。
如果小组中的一个成员开发了一组实用例程,他就可以把这些例程放在一个动态链接库中,供其他成员使用。
4、实现应用程序的国际化,往往需要使用动态链接库。
使用动态链接库可以将针对某一国家、语言的信息存放在其中。
例如,在使用AppWizard生成应用程序时,我们可以指定资源文件使用的语言,这就是通过提供不同的动态链接库实现的。
对于不同的版本,使用不同的动态链接库,常用的一些编程软件均可以编写DLL文件。
DLL 不是独立运行的程序,而是某个程序的一个部分,它只能由所属的程序调用,用户不能,也不需要打开它。
LabVIEW调用DLL文件LabVIEW支持通过调用DLL文件的方式与其它编程语言混合使用。
比如,在实际的工程项目中,用户可以用C++语言实现软件的运算部分,并把这些功能构建在DLL文件中,然后再使用LabVIEW编写程序的界面部分,并通过调用编写好的DLL来调用运算部分的功能。
LabVIEW 中是通过Call Library Function Node(CLN)节点来完成DLL文件调用的。
创建一个新的VI,右击程序框图,在Functions Palette中依次选中Connectivity——Libraries&Executables工具栏即可找到该节点(图1)。
图1 Call Library Function Node将节点放置在程序框图中,双击会出现它的配置对话框,共有四页。
第一页用于填写被调用函数的信息(图2)。
Library name or path需给出DLL文件名和路径,操作系统路径下的DLL文件,直接输入文件名也可调用,否则必须输入全路径。
在这里已经给出名字的DLL 是被静态加载到程序中的,也就是说当调用了这个DLL的VI被装入内存时,DLL同时被装入内存。
LabVIEW也可动态加载DLL,只要勾选上Specify path on diagram的选项即可。
选择了这个选项,在Library name or path中输入的内容就无效了,取而代之的是CLN 节点多出一对输入输出,用于指明所需要使用的DLL的路径。
这样,当VI被打开时,DLL 不会被装入内存,只用程序运行到需要使用这个DLL中的函数时,才把其装入内存。
Function name是需要调用的函数的名称,LabVIEW会把DLL中所有的暴露出来的函数都列出,用户只要在下拉框中选取即可。
Thread栏用于设定哪个线程里运行被调用的函数。
用户可以通过CLN 节点的配置面板来指定被调用函数运行所在的线程。
CLN 的线程选项非常简单,只有两项:Run in UI thread和Run in any thread。
LabVIEW的程序框图上直接可以看出一个CLN节点是选用图2 填写被调用函数信息的什么线程。
如果Run in UI thread,节点颜色是橙色的;Run in any thread则是浅黄色的(图3)。
图3 CLN不同线程对比通常情况下,除非使用的动态链接库是多线程安全的,CLN 中选择Run in any thread 方式;否则必须选择Run in UI thread方式。
判断一个动态链接库是不是多线程安全的,需通过以下方法:如果一个动态链接库的文档中没有明确说明它是多线程安全的,那么就要当作是非多线程安全的;在可以看到动态链接库源代码的条件下,如果代码中存在全局变量、静态变量或者代码中看不到有lock一类的操作,那么这个动态链接库也就肯定不是多线程安全的。
选择了Run in any thread方式,LabVIEW会在最方便的线程内运行动态链接库函数,且一般会与调用它的VI在同一个线程内运行。
因为LabVIEW是自动多线程的语言,它也很可能会把动态链接库函数分配给一个单独的线程运行。
如果程序中存在没有直接或间接先后关系的两个CLN节点,LabVIEW很可能会同时在不同的线程内运行它们所调用的函数,也许是同一函数。
对于非多线程安全的动态链接库,这是很危险的操作。
很容易引起数据混乱,甚至是程序崩溃。
选择Run in UI thread方式,因为LabVIEW只有一个界面线程,所以如果所有的CLN 设置都是界面线程,那么就可以保证这些CLN调用的函数肯定全部都运行在同一线程下,肯定不会被同时调用。
对于非多线程安全的动态链接库,这种方式就保证了它的安全。
让我们回到配置对话框第一页,Calling convention用于指明被调用函数的调用约定。
这里只支持两种约定:stdcall和C call。
它们之间的区别在于,stdcall由被调用者负责清理堆栈,C call由调用者清理堆栈。
这个设置错误时,可能会引起LabVIEW崩溃,也就是说如果LabVIEW调用DLL函数时出现异常,首先应该考虑这个设置是否正确。
(Windows API 一般使用的都是stdcall;标准C的库函数大多使用C call。
如果函数声明中有类似__stdcall 这样的关键字,它就是stdcall的。
)第二页是函数参数的配置(图4)。
图4 配置函数的参数DLL和LabVIEW之间传递参数,最常用的三种数据类型是数值、数值型数组和字符串。
C语言中经常把指针或者数据的地址在函数间传递,在32位操作系统中,可以使用int32数值来表示指针。
因此,当需要在LabVIEW中传递指针数据时,可以使用I32或U32数值类型来表示这个地址类型的数据。
但是,64位的程序中,数据的地址只能使用I64或U64来表示。
这样,如果一个调用了DLL函数的VI,并且函数参数中有地址型数据,使用固定数据类型的数值来表示地址,就要准备两份代码。
解决方法是使用LabVIEW中的新的数据类型Pointer-sized Integer。
这个数据类型的长度在不同的平台上会自动使用32位或64位长度。
如果在C语言函数参数声明中有const关键字,可以选中Constant选项。
布尔类型在DLL函数和LabVIEW VI之间传递没有专有的数据类型,是利用数值类型来传递的。
输入时先把布尔值转变为数值,在传递给DLL函数;输出时再把数值转为布尔值。
对于数组的传递,LabVIEW只支持C数据类型中的数值型数组,传递数组类型需要注意的的是“Array Format”要选择“Array Data Pointer”。
这个设置中还有其他两个选项,带有“Handle”的参数类型都是表示LabVIEW定义的特殊类型的。
在第三方的DLL中不会使用到数组参数作为输出值时,要记得为输出的数组数开辟空间。
开辟数据空间的方法有两种:第一种方法,创建一个长度满足要求的数组,作为初始值传递给参数,输出数的数据就会被放置在输入数组的所在的内存空间内。
第二种方法是直接在参数配置面板上进行设置。
在Minimum size中写入一个固定的数值,LabVIEW就会按此大小为输出的数组开辟空间。
在Minimum size 中选择函数的其它数值参数,而不是固定数值。
这样LabVIEW会按照当时被选择的参数值的大小来开辟空间。
字符串与使用与数组是非常类似的,实际上在C语言中字符串就是一个I8数组。
在NI软件的安装路径下打开当前使用版本的LabVIEW文件夹,通过examples\dll\data passing\Call NativeCode.llb找到简单数据类型在LabVIEW与C之间的对应关系。
部分常见关系见表1。
表1 数据类型对比第三页用于为DLL设置一些回调函数,可以使用这些回调函数在特定的情形下完成初始化、清理资源等工作(图5)。
图5 设置回调函数如果为Reserve选择了一个回调函数,那么当一个新的线程开始调用这个DLL时,这个回调函数首先被调用。