labview中dll的调用(包括生成dll)

发布者:缘到泉最新更新时间:2015-09-08 来源: eefocus关键字:LabVIEW  DLL  指针 手机看文章 扫描二维码
随时随地手机看文章
 LabVIEW支持通过调用DLL文件的方式与其它编程语言混合使用。比如,在实际的工程项目中,用户可以用C++语言实现软件的运算部分,并把这些功能构建在DLL文件中,然后再使用 LabVIEW编写程序的界面部分,并通过调用编写好的DLL来调用运算部分的功能。

  LabVIEW 中是通过Call Library Function Node(CLN)节点来完成DLL文件调用的。创建一个新的VI,右击程序框图,在Functions Palette中依次选中Connectivity——Libraries&Executables工具栏即可找到该节点(图1)。

labview中dll的调用(包括生成dll)
 

图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节点是选用

labview中dll的调用(包括生成dll)
 

 

图2 填写被调用函数信息

的什么线程。如果Run in UI thread,节点颜色是橙色的;Run in any thread则是浅黄色的(图3)。

labview中dll的调用(包括生成dll)
 

图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)。

labview中dll的调用(包括生成dll)
 

图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文件夹,通过 examplesdlldata passingCall NativeCode.llb找到简单数据类型在LabVIEW与C之间的对应关系。部分常见关系见表1。

labview中dll的调用(包括生成dll)
 

labview中dll的调用(包括生成dll)
 

 

labview中dll的调用(包括生成dll)
labview中dll的调用(包括生成dll)
 

表1 数据类型对比

  第三页用于为DLL设置一些回调函数,可以使用这些回调函数在特定的情形下完成初始化、清理资源等工作(图5)。

labview中dll的调用(包括生成dll)
 

图5 设置回调函数

  如果为Reserve选择了一个回调函数,那么当一个新的线程开始调用这个DLL时,这个回调函数首先被调用。可以利用这个函数为新线程使用到的数据做初始化工作。线程在使用完这个DLL之后,它会去调用Unreserve中指定的回调函数。Abort中指定的函数用于VI非正常结束时被调用,也就是让一个程序在运行完前停止。这些回调函数的原型在Prototype for these procedures中列出,必须要由DLL的开发者按照特定的格式实现。如果使用的DLL不是专为LabVIEW设计的,一般不会包含这样的回调函数。

  第四页是错误处理方式,用户可根据需要选择相应的错误检查级别。

  另外还需要注意的是,C语言中的struct在LabVIEW中可以使用cluster来表示,但有时需要作出相应的调整。这是因为在C语言中,struct的字节对齐是可以进行设置的,这就决定了其各元素的存放地址的可变性。C语言中的对字节对齐数可通过#pragma pack指令或在工程属性中进行指定。而在LabVIEW的cluster中,所有元素只能是1字节对齐的,所以如果要和C语言中非1字节对齐的struct对应,需要做出一些调整。比如,对于C语言中2字节对齐的struct,第一个元素如果是I8型的,在LabVIEW的cluster中第一个元素对应不变,但不能紧挨着放第二个元素,必须留一个无意义的空位。C语言的struct其实也是如此,只不过没有表现出来。所以为了方便,如果自己用C语言生成DLL文件供LabVIEW调用最好将struct都设为1字节对齐。C语言的struct中可以嵌套数组,但是这和LabVIEW中含有数组元素的cluster是不一样的,LabVIEW中需要将数组中的元素都拆开放入cluster中。

  如果C语言的struct中含有一个指针,LabVIEW中的cluster只能用一个U32数值(32位系统上,64位系统上使用U64)来表示指针的地址,而不能将指针所指向的内容放到Cluster中去。如果声明的是指向struct的指针,才能在LabVIEW中使用cluster与之对应。CLN节点的配置面板中,没有一个专门命名的“struct”或者“cluster”参数类型,应选择“Adapt to Type”就可以了。如果参数的类型就是结构而非指针,考虑到C函数参数的压栈顺序,把一个结构体作为参数传给函数,相当于把结构中每个元素分别作为参数传递给函数。图6为C语言中struct和LabVIEW中cluster的部分匹配图。

labview中dll的调用(包括生成dll)
 

图6 struct和cluster匹配

LabVIEW打包DLL文件

我们接下来学习如何使用LabVIEW来打包一个DLL文件。

  首先我们编写一个名为Scale.vi的程序,功能很简单就是对输入的数据乘上10,然后再输出(图7)。

labview中dll的调用(包括生成dll)
 

图7 scale.vi

  必须在任务管理器中才能生成.dll文件。所以我们首先建立一个project,过程如下:

点击File>>New Project:

labview中dll的调用(包括生成dll)
 

图8 生成新项目

  接着弹出是否将该VI添加到新项目的对话框:

labview中dll的调用(包括生成dll)
 

图9 是否添加VI到新建项目

  选择Add,生成新的项目管理器,将其保存在需要的路径下:

labview中dll的调用(包括生成dll)
 

 

图10 项目管理器

  右键单击项目浏览器窗口中的Build Specifications,在快捷菜单中选择New>>Shared Library(DLL),弹出对DLL文件进行设置的对话框。点击Category>>Information,根据自己需求修改Build specification name和Target filename:

labview中dll的调用(包括生成dll)
 

图11 Information页面

  点击Source Files>>Project Files>> Scale.vi>> ,弹出对话框,直接用默认值,点击OK:

labview中dll的调用(包括生成dll)
 

图12 Define VI Prototype[page]

  点击Destination>> Scale.dll,点击,可选择需要保存的路径。然后再点击Support Directory,这是指明了DLL支持文件的路径(比如数据文件之类的放在哪个文件夹),选择默认即可:

labview中dll的调用(包括生成dll)
 

图13 Destination页面

  Category中的Source Files可供用户对打包VI的属性和密码做一些设置;Advanced和Additional Exclusions可以做一些高级的设置,这些均按默认值即可。Version Information可让用户填写版本号、名称、版权、公司等信息:

labview中dll的调用(包括生成dll)
 

图14 Version Information

点击Run-Time Languages,可对支持语言进行选择,默认即可。点击Preview>>Generate Preview,可以预览到结果:

labview中dll的调用(包括生成dll)
 

图15 预览生成

点击Build,弹出生成状态对话框:

labview中dll的调用(包括生成dll)
 

图16 生成状态框

点击Done,生成完成,打开DLL文件保存的路径查看:

 

labview中dll的调用(包括生成dll)
 

图17 DLL文件保存路径

LabVIEW调用DLL文件

  LabVIEW可以方便地调用DLL文件,这些DLL文件可以是其他编译工具,如VC,生成的。

  LabVIEW可以直接通过CLN节点来调用DLL文件,以前面生成的Scale.dll文件为例。现有一个内部定时连续采集程序,通过调用该DLL文件,使读取的值为实际采集值的10倍(图18)。

labview中dll的调用(包括生成dll)
 

图18 连续采集程序

方法一

  在程序框图放入Call Library Function Node,双击弹出对话框。在Function页面的Library name or path中给入生成的Scale.dll文件的路径,Function name选择Scale,其他选项默认。

labview中dll的调用(包括生成dll)
 

 

图19 Function页面

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

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

labview中dll的调用(包括生成dll)
 

 

图20 Parameters页面

  点击“OK”,将生成的CLN的输入段连接到DAQmx Read.vi,return type输出连接到波形图表上,即可实现采集值放大10倍的功能。

labview中dll的调用(包括生成dll)
 

图21 完成后的程序

方法二

LabVIEW中还有一种方法可以调用DLL文件,在VI的选项栏,依次选择Tools——Import——Shared Library(.dll),弹出Import Shared Library对话框。

labview中dll的调用(包括生成dll)
 

图22 生成Import Shared Library对话框

  选择Create VIs for a shared library,点击Next,在Shared Library(.dll) Files中输入Scale.dll文件的路径,Head(.h) File里填写头文件的路径。

labview中dll的调用(包括生成dll)
 

图23 选择DLL文件路径和头文件路径

  点击Next,如果DLL文件中依赖其他的一些DLL文件,需要在Include Paths中填写这些文件的路径。其他选项可以根据客户需求设置,一般默认即可。这样一直点击Next到最后,选择Open the generated library,点击Finish。这样可以生成一个.lvlib格式的库文件,里面包含了Scale.vi,这是将调用该DLL文件的方法封装好的VI,只留下输入和输出接口,方便运用到LabVIEW的程序中。直接将Scale.vi拖放到刚才的连续采集中即可完成方法一的功能。

labview中dll的调用(包括生成dll)
 

图24 完成的程序

VC调用LabVIEW生成的DLL文件

  刚才介绍了LabVIEW调用DLL文件的方法,使用VC调用LabVIEW生成的DLL文件也很简单。还是以之前生成Scale 的DLL文件为例,不同的是采集电压程序使用的是C语言的例程,但和LavVIEW实现的功能相同。

  首先将先前生成Scale DLL文件时,路径下所有的文件全部复制粘帖到C语言例程的文件夹下。打开连续采集程序,点击状态栏的Project——Settings,在Project Settings对话框中加载入Scale.lib的静态链接库。

  在程序中键入#include "Scale.h",以便引入该DLL函数。下面是C程序的代码,功能是有限点采集电压,通过Scale.dll文件实现采样值放大10倍的功能。加粗部分是因为调用DLL文件所做的改动。

#include

#include "NIDAQmx.h"

#include "Scale.h"

#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else

int main(void)

{

int32 error=0;

TaskHandle taskHandle=0;

int32 read;

float64 data[1000];

char errBuff[2048]={''};

int i=0;

double x10=0;

// DAQmx Configure Code

DAQmxErrChk (DAQmxCreateTask("",&taskHandle));

DAQmxErrChk (DAQmxCreateAIVoltageChan(taskHandle,"Dev1/ai0","",DAQmx_Val_Cfg_Default,-10.0,10.0,DAQmx_Val_Volts,NULL));//

DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"",10000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,1000));

// DAQmx Start Code

DAQmxErrChk (DAQmxStartTask(taskHandle));

// DAQmx Read Code

DAQmxErrChk (DAQmxReadAnalogF64(taskHandle,1000,10.0,DAQmx_Val_GroupByChannel,data,1000,&read,NULL));

printf("Acquired %d points ",read);

for(i=0;i<1000;i++){

Scale(data[i], &x10);

printf("the %d Value is : %f ",i,x10);

}

Error:

if( DAQmxFailed(error) )

DAQmxGetExtendedErrorInfo(errBuff,2048);

if( taskHandle!=0 ) {

// DAQmx Stop Code

DAQmxStopTask(taskHandle);

DAQmxClearTask(taskHandle);

}

if( DAQmxFailed(error) )

printf("DAQmx Error: %s ",errBuff);

printf("End of program, press Enter key to quit ");

getchar();

return 0;

}

所以,使用LabVIEW不仅可以方便地调用各种编译软件生成的DLL文件,自己也能生成DLL文件供其他编译软件调用。这样,用户在编写大型项目时更加灵活,也为熟悉C语言的工程师提供了巨大的方便。本文只对LabVIEW和VC相互调用DLL文件做了简单的介绍,很多高级功能和技巧,用户可以在实际运用中逐渐掌握。


关键字:LabVIEW  DLL  指针 引用地址:labview中dll的调用(包括生成dll)

上一篇:如何使用LabVIEW和DLL传递和接受指针
下一篇:Labview与其他应用程序的接口设计

推荐阅读最新更新时间:2024-03-30 23:04

labview使用小技巧及按钮与选项卡匹配的方式
一. 选项卡控件颜色修改 在labview中,常常遇到修改某一个选项卡的问题,这一效果的实现需要调用选项卡的属性节点page,然后在里面将标签页独立,然后可以通过修改FGColor来更改不同选项卡的颜色,具体的后面板程序如下图所示: 对于前面板的三个选项卡,这种循环一次的做法用于修改第一个选项卡的背景色为黄色,剩余两个颜色保持不变,那么要修改中间的某一个选项卡的颜色,就需要有条件结构来实现了,当循环到要改变的那个选项卡时用条件结构给出一个不一样的颜色就可以将它的颜色变得不同于其他的。要把选项卡颜色变得更多那就要在这个程序的基础上去编程来实现了。 还有一个就是选项卡的自动切换,每隔一定延时给它的选项卡数值加1再给选
[测试测量]
keil 中用函数指针调用函数的参数限制
NSIC中,通过函数指针调用的函数的参数的个数没有限制,但是KeilC对此有限制,至多3个参数。因为,KeilC编译时,无法通过函数指针找到该函数的局部数据段,也就无法通过局部数据段传递参数,只能通过寄存器传递参数,所以参数个数是有限制的。碰到这个问题时解决办法是:① 将该函数改为reentarnt类型。② 修改源程序,将多个参数放在一个结构体中传递。 交叉汇编 移植的时候可能还需要编写少量的51汇编程序。汇编和C互相调用应该遵守KeilC的参数传递和返回值传递规则。为了使汇编程序也能够进行overlay分析,汇编的书写要有一定的格式。另外需要强调的一点是:被C程序调用的汇编函数可以使用所有的寄存器,而不用担心会修改C程序中使
[单片机]
使用LabVIEW与NI视觉软件进行铁路位置监测
巴黎独立公交公司负责巴黎地区快速铁路网及巴黎地铁的运营。作为世界上最繁忙的公共运输网络之一,它每年约承载着三百万左右的乘客。因此,确保具有最高安全级别的连贯性服务至关重要。 铁轨是交通运输系统基础中的一个关键因素。铁轨建造完毕后,其位置可能会随着环境状况,例如温度的变化而发生变化。因此我们必须监测铁轨位置的改变,之前,操作员一般采用的方法是检查铁轨边缘,最大频率时每两分钟人工监测一班车的铁轨和交通状况。 如今,由新视觉科技(NVT)发明的新测量方法RAILSHIFT诞生了。NVT一直致力于光学铁路基础控件研发,并不断开发新兴系统来应对各种挑战。在NI软件基础上发明的RAILSHIFT可以全自动收集,处理,分析以及产出数据。
[测试测量]
LabVIEW 2010的分析和报表特性
概览 LabVIEW 2010包含数百个信号处理与分析函数,可以对您的测量数据进行更好的分析,利用LabVIEW 2010的报表生成函数可以对分析结果进行总结和整理,从而能更好地呈现出来。 目录 1. 在线分析与报告 2. 生成报表和保存数据 3. 使用LabVIEW 2010和DIAdem 2010进行离线分析与报告 4. 试用LabvIEW 2010和DIAdem 2010 在线分析与报告 在线分析与报告是一个术语,指在数据采集应用中集成数据处理或者报表生成功能。当您从一个函数采集数据,比如DAQ助手,您可以简单地把数据连线至分析函数块,采集的数据就会被分析。 图1. 使用LabVIEW的数据流编程,在线分析和报告与数据
[测试测量]
<font color='red'>LabVIEW</font> 2010的分析和报表特性
使用图形化的开发环境——LabView开发嵌入式系统
传统设计模式所应对的挑战 嵌入式系统正在渗入现代社会的各个方面,广泛地应用于航空航天、通信设备、消费电子、工业控制、汽车、船舶等领域,据统计,在美国平均每个中产阶级家庭要使用40~50个嵌入式系统。巨大的市场需求推动了嵌入式系统向更高的技术水平发展。设计师们一方面采用性能更强大的嵌入式处理器如32位、64位RISC芯片取代传统的8位、16位微处理器;另一方面嵌入式系统也由单处理器单操作系统的传统结构向混合型Multi-core系统发展,通过采用多个处理器和OS提高系统并行度来提高系统运行效能,并且设计师们往往同时采用MPU、DSP和FPGA等多种可编程器件来增强处理能力,满足应用功能的升级。 嵌入式系统复杂性的不断增加给设计师
[嵌入式]
USB接口多路高速数据采集系统在LABVIEW平台的设计
   引言   在日常的测试测量中,经常使用数据采集卡采集数据。但是很多数据采集卡往往通过PCI总线完成数据的传输,它有诸多弊端,例如操作不便,受限于计算机插槽数量和中断资源,现场信号对计算机安全有威胁,计算机内部的强电磁干扰对被测信号也会造成很大的影响,最耗时最复杂的数据分析却由用户通过第三方软件(如VC,VB等) 在PC机上编写上位机软件来完成,因此用户不得不在这方面花费大量精力。这些问题都遏制了基于PCI总线的数据采集系统的进一步开发和应用,因此迫切需要设计一种更为简便通用的高速数据采集通信系统来完成数据采集以及与计算机的数据交互。   近年来通用串行总线(USB)以即插即用等技术优势得到了广泛的应用,INTEL等公司最
[测试测量]
USB接口多路高速数据采集系统在<font color='red'>LABVIEW</font>平台的设计
基于LabVIEW和声卡的虚拟仪器设计与实现
  摘要:为了在对采样频率要求不高的情况下进行信号的生成和分析,采用声卡取代价格昂贵的数据采集卡进行采样和输出,利用虚拟仪器开发软件LabVIEW,分别设计和实现了基于声卡的虚拟信号发生器和虚拟示波器。信号发生器可以产生方波、三角波等常用波形和自定义波形,示波器具有波形显示、图像暂停和截取以及频谱分析功能,所设计的虚拟仪器具有友好的人机界面,只需两台计算机即可进行完整的自测试。   在电子与通信行业以及试验测试中,信号发生器和示波器是应用最广泛的电子测量仪器。传统仪器的技术和性能都已经比较成熟,但存在体积较大、不易携带、功能固定、并且价格昂贵等缺点。虚拟仪器是计算机技术与仪器技术深层次结合产生的产物,代表了当前测试仪器的发展方
[测试测量]
基于<font color='red'>LabVIEW</font>和声卡的虚拟仪器设计与实现
利用多核PC技术进行图形编程
在PC行业,多核处理正在引起相当大的反响,很大程度上是因为Intel和 AMD两家公司都各自发布了其首款多核处理器。这些首款多核处理器都是在一个物理处理器中包含有两个核,或者计算引擎,因此命名为双核处理器。具有两个以上核的处理器也即将面市。 多核与多处理器 多处理器系统多年前已经出现,它与多核系统的主要区别是多核系统只有一个物理处理器,这个物理处理器包含两个或更多个核,而多处理器系统有两个或更多个物理处理器。多核系统也共享计算资源,在多处理器系统中这些资源常常是被复制的,如L2高速缓存和前端总线。多核系统与多处理器系统性能相似,但成本常常要低得多,原因是多核处理器比多个相同的单个处理器价格要低,也不需要支持多个处理
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
最新测试测量文章
换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved