LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Array of (static) subVI references

Hello all,

 

coming from a C background, where I can easily create an array of function pointers, so I can call any one with just an index tothe array, I'd like to do something similar in LabVIEW, maybe like an array of static subVI references. I can create such references to existing subVI's, and call each one by reference, and I can typedef them.  However, instead of using a case structure to select one for execution, I'd like to at least try to implement an array of some sort of vi references, and use an enumerated index to select which one to call.  I have searched about, but haven't seen anything remotely like what I'm looking for.  Is this possible?  I am hoping to usae such a mechanism for a different (?simpler?) approach to state machine design.  Thanks.

0 Kudos
Message 1 of 24
(4,737 Views)

It sounds like you could benefit from dynamic dispatch using the command pattern. See the knowledge base pointed to here on Lava. Also you might want to look at the simple introduction to LVOOP.

=====================
LabVIEW 2012


Message 2 of 24
(4,733 Views)

That is not going to be quite that simple.  Strict Static references to vi's include information about the connector pane and array elements must have all identical properties (except Value and Text.text for obvious reasons).  Calling by referance (which is what it sonds like you want to do to emulate a C style program) requires a strict type reference because LabVIEW is a data flow language so the connector pane terminals must be linked to a datatype.  If the connector panes are dissimilar on your vis building them into an array will coerce them to generic static references (lowest ancestor class that they both inherit from)

 

Some times you can get a group of closely related "Functions" and define a connector pane requirement and call them by referance (Even asynchronously in recient LabVIEW versions)

 

The LabVIEW state machine design pattern leverages the advantages a dataflow language has.  I grant you that If I were writing in C your approach would make more sense since you only need to pass a pointer index.  Welcome to LabVIEW- its not C


"Should be" isn't "Is" -Jay
0 Kudos
Message 3 of 24
(4,728 Views)

Steve's suggestion is the way to go, but it is possible to build an array of references to VIs.  If you plan to call them using a call by reference node, then they must all have the same connector pane.  I haven't done this exactly, but from my experience with, and understanding of, VI Server, there's no reason it wouldn't work.

0 Kudos
Message 4 of 24
(4,727 Views)

"it is possible to build an array of references to VIs" - I must confess, that is the answer that I wanted to see.

"they must all have the same connector pane" - of course, just as with an array of function pointers in C, all functions must have the same "interface" of parameters and return type to enable the same call to any function listed in the array.

Although I am definitely interested to explore OOP in LV, like I said, I like the positive answer and the basic principle, at least at this exploratory stage, of an array of subVI references, but now need to figure out exactly how to make it work.  I do have a simple example, with 3 dummy subVIs, with identical connector interfaces, and have created subVI references, and typedef'd them, and I can call any one by reference.  But I haven't figured how to "drop" such a thing into a constant array to define an array of VI references; I am still perplexed (learning).  I gratefully welcome any clue, answer, solution, or reference.  Thx again very much.

Message 5 of 24
(4,714 Views)

Create a static reference to each VI individually and then connect the references to Build Array.

 

Any chance you want to upload your sample code?  That you aren't aware of this use of Build Array, but are trying a complicated scheme of calling by reference, suggests that you are trying to write code that looks like your idea of how to do it in C, instead of learning good LabVIEW programming style.  Such designs almost always lead to poorly written and unnecessarily complex LabVIEW code (I've had the misfortune of maintaining some of these and have completely rewritten others). If you upload your code, we might be able to point you at a better way to achieve your goal.

 

I'm not sure where the type defs come in; I can't think why you'd need one here, and you definitely don't need one for each VI.

0 Kudos
Message 6 of 24
(4,710 Views)

Thanks very much for that little tip, which really helped, and takes me one step forward.

I've attached an example of what I'm getting at.  There is one main program, and three dummy subVI's, with identical in/out interfaces, and each simply outputs a unique value for identification, which is displayed on the front panel.  As is, there are 3 exploratory stages: (A) explicit VI calls, and the outputs of each are displayed on the front panel, (B) a static VI reference is created for each VI, and each is selected in a case structure; that works OK, and (C) implements a simple state sequence, driven by a next-state table, and calls each corresponding subVI from the table, created as you suggested, using the state as index.

So the solution you offered works well.  BUT my main question, and objective, is: can I create an i-n-i-t-i-a-l-i-z-e-d constant array of subVI references, where I can clearly read each element by name, just as I can read the entries in the next-state table?

The REAL motivation for this approach is to implement a self-documenting next-state transition table, which can greatly help to follow and debug the code execution from state to state, whereas determining the next state inside a case structure makes it more difficult (debatable, I suppose).

Also, it seems that there is a common pattern underlying the case-structure based state machine, which can be more efficiently captured in such a state table approach.  However, since I am a relative newbie, I am open to "illumination" from more experienced LabVIEW programmers and commentaries to this proposed approach.  Thx again very much.

0 Kudos
Message 7 of 24
(4,699 Views)

@alexwk wrote:

So the solution you offered works well.  BUT my main question, and objective, is: can I create an i-n-i-t-i-a-l-i-z-e-d constant array of subVI references, where I can clearly read each element by name, just as I can read the entries in the next-state table?


I'm still confused here.  The output of build array is effectively an initialized array of subVI references, and if you lined up the references it would be easy to read.  Are you trying to generate a 2-dimensional array of them similar to the next-state table?


@alexwk wrote:

The REAL motivation for this approach is to implement a self-documenting next-state transition table, which can greatly help to follow and debug the code execution from state to state, whereas determining the next state inside a case structure makes it more difficult (debatable, I suppose).


Perhaps I'm missing the goal, but I think you're overlooking the simple solution here.  Put the relevant code inside each case of a case structure, but handle the next-state selection outside the case structure.  Then you can use your next-state table to drive the sequence, while maintaining the efficiency and readabillity advantages of direct subVI calls and avoiding references.  It would look like this:

next state table with subVI calls.png

Now it's easy to see what happens in each state because you can find it quickly in the case structure and you can debug it using standard LabVIEW debugging techniques (which can be more challening when calling VIs by reference), without giving up the next-state table.

Message 8 of 24
(4,679 Views)

You can create an array of non-strict VI references and use them to call the VIs dynamically, the caveat is that passing parameters can get messy in that you have to pass them by name, getting data out is a little easier in that there is a method that lets you get the contents of all the controls or indicators.

 

Mike...


Certified Professional Instructor
Certified LabVIEW Architect
LabVIEW Champion

"... after all, He's not a tame lion..."

For help with grief and grieving.
0 Kudos
Message 9 of 24
(4,674 Views)

Thanks again for the feedback.  I think I have what I wanted; see attached.

Referring to nathand's comments, yes, I should have been a bit clearer, in addition to the fact that I did miss a few subtleties myself.  By an initialized const array, I meant one created just like the next state table is, by dropping VI references into a const array box, and editing each element, i.e. without using a build array function.  However, for the present purposes, I find the build array approach quite suitable.

One of my motivations is precisely to avoid the case structure, and just use a combination of current state and event enumerated indices to determine the next state and corresponding action.  In my thinking, the next state table uniquely documents the top view of a state transition diagram, whereas a case structure requires to look into each case to see how the next state is determined, adding one level of depth to trace code execution.  It seems important to distinguish the top view, described by the table, vs. internal details of each state's code execution, just like distinguishing a C function's internal operation vs interface and relationship to the rest of the program.  Please have a look at the front panel and relate it to the code.  The present version of this simple exmple does provide for user-selected event to determine state sequence.  Also keep in mind that I a relative newcomer, with C background, and so I'm naturally, if mistakenly, projecting C concepts onto my LabVIEW code.  I would appreciate any comments re. efficiency of code execution, memory usage, etc.  Just like every case in a case structure receives the same information from shift registers and variables pertaining to the state machine execution, so must all subVI's naturally have the same in-out parameters, which could also all be bundled into a cluster and passed by reference (next thing to explore).

BTW, how do yu copy a segment of code into these discussions? 

Thanks again very much for all input.

0 Kudos
Message 10 of 24
(4,637 Views)