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文件夹,经过 examplesdlldata passingCall NativeCode.llb找到简略数据类型在LabVIEW与C之间的对应联系。部分常见联系见表1。
表1 数据类型比照
第三页用于为DLL设置一些回调函数,能够运用这些回调函数在特定的景象下完结初始化、整理资源等作业(图5)。
图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的部分匹配图。
图6 struct和cluster匹配
LabVIEW打包DLL文件
咱们接下来学习怎么运用LabVIEW来打包一个DLL文件。
首要咱们编写一个名为Scale.vi的程序,功用很简略便是对输入的数据乘上10,然后再输出(图7)。
图7 scale.vi
有必要在使命管理器中才干生成.dll文件。所以咱们首要树立一个project,进程如下:
点击File>>New Project:
图8 生成新项目
接着弹出是否将该VI增加到新项目的对话框:
图9 是否增加VI到新建项目
挑选Add,生成新的项目管理器,将其保存在需求的途径下:
图10 项目管理器
右键单击项目浏览器窗口中的Build Specifications,在方便菜单中挑选New>>Shared Library(DLL),弹出对DLL文件进行设置的对话框。点击Category>>Information,依据自己需求修正Build specification name和Target filename:
图11 Information页面
点击Source Files>>Project Files>> Scale.vi>> ,弹出对话框,直接用默认值,点击OK:
图12 Define VI Prototype