5.3.3 当前上下文(ThisContext)属性
在变量窗格中还有一级属性ThisContext,它的数据类型很特殊,即Sequence Context(序列上下文)。“序列上下文”从字面上理解就是一个序列的所有信息,因此展开ThisContext时,会发现它同样包含了Locals、Parameters、FileGlobals、StationGlobals、ThisContext、RunState等所有变量窗格中的一级属性,如图5-20所示。由此可见,ThisContext包含的信息量是很大的。
在5.3.2节介绍运行时属性时,提到RunState容器下包含的动态属性RunState.Root、RunState.Main、RunState.Caller等在序列编辑状态时值为空,在序列执行时TestStand传递了序列上下文类型引用给它们,这样它们就包含了不同序列的上下文信息,如图5-21所示。
图5-20 展开ThisContext一级属性
图5-21 RunState容器下的Sequence Context类型子属性
ThisContext的数据类型是序列上下文,而且它指向的是当前序列,一般会将ThisContext作为参数传递给代码模块或者其他序列,这相当于把当前序列的所有信息传递了出去。细心的读者可能会发现,在图5-21中,变量窗格中有一个ThisContext,而RunState下也有一个ThisContext,这两个属性是否有联系?回答是肯定的,它们其实是同一个属性,ThisContext就是RunState.ThisContext的拷贝,“This”这种表达方式指的就是创建一个指向自己的引用。TestStand为了方便数据传递和访问起见,在每个序列上下文容器中都额外创建了ThisContext,用于指向这个序列上下文本身。可以预见的是,如果将ThisContext传递给代码模块,在代码模块中就可以访问当前序列的所有信息,也可以对序列中属性和变量的值进行修改。
下面的练习读者可任选其一。
【练习5-4A】传递ThisContext属性给LabVIEW代码模块。
在本练习中,将ThisContext作为参数传递给LabVIEW VI,然后在VI中获取ThisContext中属性和变量的值。
(1)打开序列编辑器,新建一个序列文件并将其保存为<Exercises>\Chapter 5\Sequence Context\ThisContext-LabVIEW.seq。
(2)创建数值型局部变量Locals.input_a和Locals.output_b,以及字符串型局部变量Locals.status。
(3)在插入选板中选择模块适配器为“LabVIEW”。
(4)添加动作步骤,并将其命名为“Get Local Variable”,在模块页面VI路径中选择Get TestStand Variable through ThisContext.vi,该VI位于<Exercises>\Chapter 5\Sequence Context。读者可以查看它的程序框图,如图5-22所示,非常简单,调用了TestStand选板函数TestStand-Get Property Value.vi,它是一个多态函数,这里选择多态实例为“Number”。它的输入参数为“Sequence Context In”,结合“Lookup String”就可以获取子属性或变量,查找字符串就是子属性或变量的访问路径,如ThisContext.RunState.Sequence。第11章中还会详细介绍查找字符串的方法。
图5-22 Get TestStand Variable through ThisContext.vi程序框图
说明:所有TestStand选板函数都是在TestStand安装时自动添加到LabVIEW应用开发环境中的。
回到TestStand,在参数列表中,Sequence Context In的值为“ThisContext”,Lookup String的值为“"Locals.input_a"”,其他参数设置如图5-23所示。
(5)添加动作步骤,并将其命名为“Get Property Value”,在VI路径中选择Get TestStand Property through ThisContext.vi,该VI位于<Exercises>\Chapter 5\Sequence Context。同样可以查看它的程序框图,如图5-24所示,它调用的也是TestStand选板函数TestStand-Get Property Value.vi,选择多态实例为“String”。
回到TestStand,在参数列表中,Sequence Context In的值为“ThisContext”,Lookup String的值为“"RunState.Sequence.Main[Get Local Variable].Result.Status"”,其他参数设置如图5-25所示。
图5-23 Get Local Variable步骤参数列表
图5-24 Get TestStand Property through ThisContext.vi程序框图
图5-25 Get Property Value步骤参数列表
(6)添加消息对话框步骤,在消息表达式中输入“"The value of Locals.output_b is"+Str(Locals.output_b)+"\n"+"The status of step\"Get Local Variable\"is"+Locals.status”。
(7)保存序列文件,执行菜单命令“ExecuteSingle Pass”,观察消息对话框的弹出结果,如图5-26所示。
图5-26 消息对话框结果
在范例资源的第5章练习中,例程<Exercises>\Chapter 5\Sequence Context\ThisContext-LabVIEW-solution.seq完成的是上面的练习,读者可以通过菜单命令“ExecuteSingle Pass”运行该范例并观察结果。
【练习5-4B】传递ThisContext属性给CVI代码模块。
在本练习中,将ThisContext作为参数传递给LabWindows/CVI生成的DLL,通过DLL获取ThisContext中的属性和变量的值。
(1)打开序列编辑器,新建一个序列文件并将其保存为<Exercises>\Chapter 5\Sequence Context\ThisContext-CVI.seq。
(2)创建数值型局部变量Locals.input_a和Locals.output_b,以及字符串型局部变量Locals.status,保持初始默认值。
(3)在插入选板中选择模块适配器为“LabWindows/CVI”。
(4)添加动作步骤,并将其命名为“Get Local Variable”,在模块页面DLL路径中选择“PassThisContext.dll”,该DLL位于<Exercises>\Chapter 5\Sequence Context\CVI Project。PassThisContext.dll一共导出两个函数:Get_Num_Variable和Get_Str_Variable,分别获取数值型属性/变量的值和字符串型属性/变量的值(如图5-27所示)。其中调用了TestStand函数库TS_PropertyGetValNumber和TS_PropertyGetValString,位于“NI TestStand API 20××Property ObjectValues”下,如图5-28所示。它们有两个关键的输入参数:ThisContext和LookupString。ThisContext结合Lookup String就可以获取子属性或变量,查找字符串就是子属性或变量的访问路径,如ThisContext.RunState.Sequence。第11章中还会详细介绍查找字符串的方法。
图5-27 PassThisContext.dll导出函数原型
图5-28 LabWindows/CVI中的TestStand函数库
说明:关于TestStand函数库,第13章中会详细介绍,包括如何将函数库添加到工程中。
回到TestStand,选择函数Get_Num_Variable,在参数列表中,Sequence Context In的值为“ThisContext”,Lookup String的值为“"Locals.input_a"”,其他参数设置如图5-29所示。
图5-29 Get_Num_Value步骤参数列表
(5)添加动作步骤,并将其命名为“Get Property Value”,在模块页面DLL路径中同样选择PassThisContext.dll,选择Get_Str_Variable函数。在参数配置列表中,Sequence Context In的值为“ThisContext”,Lookup String的值为“"RunState.Sequence.Main[Get Local Variable].Result.Status"”,其他参数设置如图5-30所示。
图5-30 Get_Str_Value步骤参数列表
(6)添加消息对话框步骤,在消息表达式中输入“"The value of Locals.output_b is"+Str(Locals.output_b)+"\n"+"The status of step\"Get Local Variable\"is"+Locals.status”。
图5-31 消息对话框结果
(7)保存序列文件,执行菜单命令“ExecuteSingle Pass”,观察消息对话框的弹出结果,如图5-31所示。
在范例资源的第5章练习中,例程<Exercises>\Chapter 5\Sequence Context\ThisContext-CVI-solution.seq完成的是上面的练习,读者可以通过菜单命令“ExecuteSingle Pass”运行该范例并观察结果。
因为“ThisContext”就是当前的序列上下文,动作步骤Get Local Variable通过查找字符串"Locals.Input_a"获取到局部变量Locals.input_a的值,进行一定运算后再返回给Locas.Output_b。动作步骤Get Property Value通过查找字符串"RunState.Sequence.Main[Get Local Variable].Result.Status"获取前一步骤Get Local Variable的状态,因此在消息对话框中会得到它的状态“Done”。这个练习主要是告诉我们,将ThisContext传递给代码模块,只要能够提供属性和变量的访问路径,那么当前序列的所有上下文信息在代码模块中都是可以访问并被修改的。
说明:本书不会对LabVIEW或LabWindows/CVI中的具体编程做更细致的介绍,读者可以参考书中提供的范例代码,以加快对知识点的掌握。