LabVIEW 2009 新功能 – 传引用

以前版本的LabVIEW虽然也有多种方法可以让数据以引用的方式在程序间传递,但是用起来都有些麻烦。LabVIEW有了构建数据传引用的节点,大大简化了传引用的程序代码。

新添的有关传引用的两个节点在函数选板“Programing->Application Control->Memory Control”中,分别是“New Data Value Reference”和“Delete Data Value Reference”。“New Data Value Reference”用于创建一个数据的引用,“Delete Data Value Reference”可以从引用中取回原来的数据。

引用最主要应用于多线程程序中。如果两个线程同时对同一份数据进行修改,则必须使用传引用的机制。否则,使用值传递的方式,数据在数据线分叉的地方,就会编程独立的两份,之后在两个线程内分别修改的是两份完全独立的数据,没办法对同一份数据进行修改的。

比如下图这个程序,程序输入了一个数组,然后需要在两个并行的子VI中同时对这个数组中的数据进行修改。每个子VI可能修改了数组不同的元素,程序运行结束产生的数组应当把两个子VI中的修改都包含进来。因此,程序一开始需要数组数据生成一个引用,然后把引用分别传递到两个子VI中去。两个子VI都运行结束后,在从引用中取回数据。

LabVIEW中已有的函数还都是为值传递设计的,所以使用值传递少不了把数据取出、放回的过程。这以过程中,可能又会产生数据拷贝,效率会比较差。好在我们可以使用“In Place Element Structure”结构来处理从引用中取出、放回数据的过程。配合了“In Place Element Structure”结构使用后,LabVIEW会尽量使用数组原地址,而不是把从引用中取出的数据复制一份,这样就做到了传引用与效率的兼顾。比如下面两图中的程序,功能是完全相同的,但LabVIEW会对下面一幅图中的程序进行优化,提高效率。

 

《我和LabVIEW》补充与注释

12 thoughts on “LabVIEW 2009 新功能 – 传引用

  1. 从第三方DLL中把数据拿给LabVIEW用,只能copy一份,没有效率更高的办法。不过,如果你自己写DLL,倒是可以利用LabVIEW提供的一些API,对LabVIEW中的数据直接操作,避免拷贝。后一种方式比较麻烦,我还没有看到过实际的应用。

  2. Qizhen Ruan,“实际上,就是在CLN节点中,通过配置参数的类型为U32,把一个指针数据的地址传出来,再传递给其它CLN使用”,您说的这个做法我已在目前的程序中实现,但是我觉得并不高效,只能一个一个数据通过CLN来读,特别是当数据量多时,估计LabView对返回的数又copy了,我想的做法是:在LabView中可否直接访问这段内存,或者更好的情况是LabView可以直接处理这段连续的内存的数据而画出波形图。我在网上搜索了很多,但是没找到LabView可以高效访问内存的做法,还请赐教,谢谢。

  3. Michael Xiong,对应书中的图片,有范例可以下载,你可以把示例下载下来,仔细看一下。实际上,就是在CLN节点中,通过配置参数的类型为U32,把一个指针数据的地址传出来,再传递给其它CLN使用。

  4. 您好,我有一本您的“我和LabView” ,在 "4.8.5 借助 C 语言" 这节中提到 : “ ……LabView传递的只是这数据空间地址值。后续程序若需要用到被引用数据,则可以通过地址值 得到数据的内容 ………… 见图 4.65”, 对图4.65我没看明白到底是如何通过地址取到数据的,我目前开发的一个程序就需要这样的功能,LavView 调用DLL(c++) 返回一个c分配的内存的地址,而后在LabView中通过这个地址取到值。

  5. 从接触LABVIEW到现在,不到一年时间感受到了LABVIEW的强大,今天有幸看到您的日志,受益很多,非常感谢最近了解到LABVIEW FOR ARM 您公司对这方面的说明比较少,我现有LPC2478ARM,ULINK2,看了好久您公司网站的PORTING,没有成功,加上本来英语也不太好,不知道您能不能提供点这方面的帮助,谢谢

  6. LabVIEW使用值传递,因为它是自动多线程的程序。而C++,C#不是,所以他们可以使用传引用,但是使用C++,C#编写多线程的程序就比LabVIEW麻烦得多。详细的你可以参看一下我专门讨论传值传引用的文章。如果需要传引用可以使用“New Data Value Reference”和“Delete Data Value Reference”节点,配合“In Place Element Structure”结构使用,能够保证资源互斥。

  7. 仔细考虑后,使用队列传递对象引用似乎可以实现互斥同步访问同一类对象实例。最后剩下的问题是,出队列操作会阻塞哪一重循环呢(如果该操作位于多重循环里),是离它最近那个?当然我可以通过试验来验证,但还是希望能听听专家的意见。

  8. 在LabView里,类对象的传递也是值传的。在实例里有通过队列来实现引用传递。现在似乎有了新的方法,不错。不过还是觉得LabView里应该默认让类对象为引用传递(现代的语言里基本都是这样做的了,如C#)。我在实际应用中的遇到的问题是,可能并行地去访问我的类对象(我有一个循环不停地访问它以采集数据,另一个循环需要偶尔访问该对象发送控制命令出去),访类封装了对独占设备(如串口)的访问。这问题仍困扰我,因为我对LabView还不是很熟悉。如何在LabView里实现对对象的引用访问,同时还要解决互斥访问I/O对象问题。这个目前有些超出个人能力了,望大师指点迷津,谢谢!

  9. 你这个问题问的太笼统了。全局变量与这个传引用节点最大的区别应该是:使用传引用节点仍然需要使用数据线把所有使用到这个数据的地方连接起来,而全局变量不用。

  10. 网友 says:解答一个网友的问题,暂时存一下请教大侠:LabVIEW2009中的New Data Value Reference和Delete Data Value Reference在实际应用中的好处,最好能举例,谢谢。Qizhen says: LabVIEW 以前传引用很麻烦,现在简单了。比如说你要在两个并行的for loop 中同时修改同一个数值数据。以前直接把U32数据,分别传到两个循环结构里是不行的,因为数据一旦分叉,就是独立两份了。若想在两处修改同一数据,就先用 New Data Value Reference生成数据的引用,把引用传递到不同循环结构里就可以了。这类似于C++ 中,int& data,这样的传参方式。网友 says: 但一个数组(或任意数据类型)通过New Data Value Reference变成引用后传到不同的地方,当不同的地方要处理这个数组中的任一个元素都必须要使用Delete Data Value Reference来还原数据(产生复制,当然是临时的),视乎没有解决太多数据流的缺陷。Qizhen says: 数据流自然的传递数据方式是按照值传递,如果没必要,应该使用值传递,一次传给每一个模块,对数据进行处理,尤其是数组这种数据量很大的类型。如果一定要使用Reference,可以配合In Place Element Structure结构来使用 在In Place Element Structure结构内部把数组解开,这样LabVIEW会尽量使用数组原地址,而不是复制数组。

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

You are commenting using your WordPress.com account. Log Out /  更改 )

Google photo

You are commenting using your Google account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

Connecting to %s