1.为什么
在实际项目中,往往会使用第三方提供的dll来调用别人封装的函数来完成项目任务,但有时会用到一些带指针的参数,比如int * p;int * * dp相信指针对于一些人来说是很头疼的事情,那么在LabVIEW中如何正确使用呢?一开始我也是模棱两可,凑合着用,忍受着偶尔内存出错,无法顺利打包exe的尴尬。因此,我利用这个项目的应用,对相关内容进行了深入的探索,我想出了这个总结。

2.什么?
本总结主要解决以下问题:
关于DLL中一级指针参数的使用;关于DLL中二级指针参数的使用;使用GetValueByPointer.xnode导致程序包exe运行异常;3.怎么会?
为了解释方便,我用C封装了几个函数,输出一个111.dll文件进行测试。下图显示了函数的原型和定义:
1.主指针
一级指针相对简单易懂,就是内存中的地址。只需要注意它的数据类型,配置要和函数原型声明中的参数类型一致。labview中调用库函数节点很好的支持了一级指针。以TestFunc3函数为例。
在程序框图面板中,放置calllibrary fundation node.vi,双击打开配置面板:
1.选择DLL所在的路径。
2.选择要调用的函数的名称。
3.选择呼叫约定;
进入参数配置面板。函数声明中有一个参数,是无符号的char *类型。在左边添加一个参数,然后选择数组的类型,然后选择数组中存储的数据类型。这里是一维数组,默认1不变。然后数组格式是数组数据指针,分配最小内存大小,这里设置为10。这时,你可以在底部看到,函数原型已经被配置成和DLL中的一样了。基本上问题不大。
运行,结果和预期的一样。
如果不分配内存大小,将无法获得正确的结果,甚至会报错。将大小更改为“”,操作有错误。
内存大小可以在配置面板中指定,也可以在程序框图中通过初始化指定长度的数组来分配。显然,这样更灵活,如下图所示。
2.次级指针
也就是指针的指针,相当于双地址。简单理解下图:A代表A在内存中的地址,B代表B在内存中的地址。
在内存中打开一个空块来存储字符串A“Hello LabVIEW!”,B是一级指针,存放A的地址,字符串A可以通过*解析,B的地址由c存放,字符串A也可以通过双重解析*得到)。
接下来,我们来看看如何在LabVIEW中配置这个参数类型。在LabVIEW中,我们不能直接配置二级指针类型,但是可以通过一级指针得到实际数据的地址,然后通过解析地址得到相应的数据。

以TestFunc2函数为例。
添加一个形参cp,选择Numeric作为类型,Signed 32-bit Integer作为数据类型,并将其作为指针传入。
根据上面的例子,经过这样的配置,cp实际上保存的是B的值,也就是变量A A的地址,和数据串“Hello LabVIEW!”离地址解析还差一步。
是时候出现工具GetValueByPointer了,这个路径可以找到,以2012版本为例。
传入指针参数,然后指定数据类型,这里是一个字符串,就可以得到正确的结果。如下图所示。
GetValueByPointer可以用来方便的解析指针,使用起来也非常简单。可以根据实际的数据类型进行配置。
关于指针解析,LabVIEW还提供了一个间接函数,MoveBlock函数。两者的一个区别是:
MoveBlock:级别更低,控制更多,可以处理任何数据类型;
GetValueByPointer:简单易用,适合大部分数据类型,无法处理一些复杂类型;
根据当前查看的数据,MoveBlock函数应该封装在LabVIEW的静态库中,调用方法如下:
打开库函数节点,在路径中输入“LabVIEW”;
此时,函数名列表将更新许多函数名,包括MoveBlock;
在参数面板中,参考以下配置:
我这里配置的adress输入法是Value,不是指向Value的指针。原因是通过直接引入的TestFunc2的配置,返回的已经是指针了,所以这里我选择值来输入。然后指定目标数据类型和大小,并运行更改以获得正确的结果“Hellow LabVIEW!”。
3.打包exe时出现异常
这里打包的主要问题是使用了GetValueByPointer。正常打包完成后,操作会发现没有报错,但是不能正确得到预期的结果,或者出现下图所示的错误。
出现这些异常的原因是GetValueByPointer.xonde根本没有正确执行。因为封装在lvimptsl.dll中的GetValueByPointer函数是为它调用的,所以我们在打包时必须包含lvimptsl.dll。

将lvimptsl.dll纳入项目;
打包时,在目的地创建一个新的资源文件夹,然后总是包含;
在源文件设置中,将其添加到支持路径资源中;
这样打包后就可以正常运行了。
在摸索的过程中,我参考了很多大牛前辈的经验总结。谢谢您们。以上内容如有错误请指正,万分感谢。


