Jump to content

Saving a VI within a VI or an XNode


Recommended Posts

It is possible to save a VI as a buffer (string) using scripting. A reference to this buffer saved VI can then be opend using scripting as well. The problem with this kind of VI is that LabVIEW doesn't know they exist and cannot recompile them when something referred by the VI changes.

I'd like to script a top-level VI for each XNode instance so that the content of the scripted VI depdens on the configuration of the XNode. The important issue here is that the VI must be top-level i.e. I need to be able to call it asynchronously. At execution time XNodes are always called syncrhonously to my knowledge, aren't they? So I was thinking placing a static VI reference on the code generated by the XNode and use this reference to call the VI asynchronously using Run VI method.

The problem is that I don't find good solution to do this. If I script a new VI, it needs to be saved somewhere. From usability point of view, the internal VI needs to be unexisting for the user. So I cannot save it into an external file. I could save it as a buffer that's stored as state parameter of the XNode. However I expect that this method would lead into many problems as LabVIEW cannot compile the VI in the buffer when something changes. For example if a VI containing such XNode is opened in another LabVIEW version, the buffer would not be recompiled properly.

So I guess the only option I can think of is to save the VI within the XNode containing VI or the XNode instance somehow. I know LabVIEW class controls are VIs stored within an lvclass file. I'd like to kind of save my scripted VI within the VI as a kind of internal subVI that would be recompiled when the outer VI is recompiled. But I've no idea if this is possible. Does anyone have any idea if this is possible? I would not like to use explicit linker depdendesies as Aristos Queue so strongly demanded not to use them. That is always the last option left...

Tomi

Link to comment

Tomi,

I have used this VI buffer technique in the past several time (basicaly reading the VI as a text file and saving the end result as default in a string control). I don't understand why you say that LabVIEW will not recompile this VI. As soon you "extract" this VI to disk, it becomes like any other VI. I guess I don't quite understand your use case scenario.

Note: I have seen the scripting buffer function and while I never had to try them, I always though that the App:Open.VI from Buffer method was the equivalent of extracting the VI to a temp location and them opening a ref to it.

PJM

Link to comment

QUOTE(PJM_labview @ Dec 6 2007, 07:48 PM)

I have used this VI buffer technique in the past several time (basicaly reading the VI as a text file and saving the end result as default in a string control). I don't understand why you say that LabVIEW will not recompile this VI. As soon you "extract" this VI to disk, it becomes like any other VI. I guess I don't quite understand your use case scenario.

But in my use case I would never be able to save the VI into a file. It would only exist as a string buffer in a state information of an XNode. As LabVIEW doesn't know this particular string is a VI, it doesn't know that it needs to be recompiled every now and then. I was indeed looking for methods to get it recompiled without saving it to an external file. External file would be usability wise so bad an alternative that I cannot consider it as an option. Nobody would accept a situation where LabVIEW would generate several support VIs for every user defined VI on its own. Only if these VIs can be somehow stored within the VI and LabVIEW would load them into memory together with the VI with front panels closed, only then the solution would be acceptable.

So is there a way to store a VI inside another VI and get LabVIEW to load the inner embedded VI into memory when the outer VI loads to memory and compile the inner VI like any other VI and save it together with the outer VI when ever the outer VI is saved?

Link to comment

QUOTE(Tomi Maila @ Dec 6 2007, 03:27 PM)

So is there a way to store a VI inside another VI and get LabVIEW to load the inner embedded VI into memory when the outer VI loads to memory and compile the inner VI like any other VI and save it together with the outer VI when ever the outer VI is saved?

Ah, wayward traveler! A word I would whisper in thy ear! Know ye the toolkit known as Block Builder? 'Tis a tool of the devil, the one they call "Express." But in yon toolkit ye shall find the secret that you seek -- the magic of hiding one VI within the confines of another. I canna say how such transsubstantiation is accomplished, for I have ne're learned the trick. But a black magician such as yourself should have no trouble ferreting out the diamond in the rough.

Link to comment

QUOTE(Aristos Queue @ Dec 7 2007, 07:56 AM)

Ah, wayward traveler! A word I would whisper in thy ear! Know ye the toolkit known as Block Builder? 'Tis a tool of the devil, the one they call "Express." But in yon toolkit ye shall find the secret that you seek -- the magic of hiding one VI within the confines of another. I canna say how such transsubstantiation is accomplished, for I have ne're learned the trick. But a black magician such as yourself should have no trouble ferreting out the diamond in the rough.

Thank you, ah mister, for thy guidance! Thy words of wisdom of great help are! Lord praise you mister, lord praise.

Link to comment

Aristos Queue, it works! :) But only within development environment :( There seems to be a bug in builder that drops the instance VIs from the build... I reported it to NI and for their shake I hope they will fix it soon. I'm still going to use this method and if not fixed, I guarantee they are going to get a plenty of bug reports from you all ;)

If a static VI reference is created into an instance VI (Express VI isntance), the instance VI can be referred using a VI reference. If one wishes to use Run VI method, one needs to place the instance VI itself on a disable diagram to avoid reserving the instance VI for subVI exection when the main VI executes. This method works properly in development environment but build applications exit with internal error. It's presumable that builder simply mistakenly excludes the instance VI from the build.

post-4014-1197165007.png?width=400

To reproduce:

- Open the attached project

- Open the only VI in the project

- Run VI in the development environment, notice that the instance VI is executed properly

- Now close the VI

- Build an application according to the build specifications

- Execute the application, note that it doesn't execute but stops at internal error

Link to comment

QUOTE(Tomi Maila @ Dec 8 2007, 04:18 PM)

It's presumable that builder simply mistakenly excludes the instance VI from the build.

It's not a mistake to exclude the instance VI... you commented out the Express VI node, thus app builder would assume that the instance VI would never be callable. Try using a case structure with constant FALSE instead (use a control, not a block diagram constant or LV may again get too smart for you). Again, just a guess.

Link to comment

QUOTE(Aristos Queue @ Dec 9 2007, 09:27 AM)

It's not a mistake to exclude the instance VI... you commented out the Express VI node, thus app builder would assume that the instance VI would never be callable. Try using a case structure with constant FALSE instead (use a control, not a block diagram constant or LV may again get too smart for you). Again, just a guess.

I diagree. I think it is a bug. All VIs referred by static VI references should be included into the build. Instance VIs should not be any different in this respect. When I place any other subVI on the disable diagram and create a static VI reference to this subVI, builder includes the VI into the build, because I have the static VI reference referring to it.

The method suggested using case structure instead of disable diagram doesn't work. LabVIEW reserves all VIs within case structure for subVI execution. Then they cannot be called with RunVI method because they are in a state Run not compatible with top-level exection.

Tomi

Link to comment

QUOTE(Tomi Maila @ Dec 9 2007, 11:01 AM)

I diagree. I think it is a bug. All VIs referred by static VI references should be included into the build. Instance VIs should not be any different in this respect. When I place any other subVI on the disable diagram and create a static VI reference to this subVI, builder includes the VI into the build, because I have the static VI reference referring to it.

The method suggested using case structure instead of disable diagram doesn't work. LabVIEW reserves all VIs within case structure for subVI execution. Then they cannot be called with RunVI method because they are in a state Run not compatible with top-level exection.

Tomi

Reentrancy?

Jeff Washington once mentioned that all express VIs needed to be reentrant.

Include it explicitly in the build file?

Ton

Link to comment

QUOTE(tcplomp @ Dec 9 2007, 12:18 PM)

Include it explicitly in the build file?

I don't think this is possible to explicitly include an instance VI into a build. The instance VIs are saved within outer VI and I don't think you can explicitly select them to be included, at least not interactively. Maybe one could edit the build specification manually but that's not very user friendly. I'm working on a user friendly framework and am not ready to accept usability wise poor solutions.

An instance VI path is something like

C:\My Project\My Outer VI.vi\1

where 1 is the name of the instance VI. The qualified name of the instance VI is

My library.lvlib:My Outer VI.vi:Instance:1

Actually I've not tested if instance VI will be included into the same library into which the outer VI belongs to.

Tomi

Link to comment

QUOTE(Aristos Queue @ Dec 9 2007, 11:42 PM)

Your logic would hold except for one bad assumption -- you're assuming that instance VIs are like any other VI. But instance VIs aren't regular VIs and were never designed with your use case in mind. They cannot exist without the calling node, and if you strip the calling node during app building then the instance VI goes away. These VIs make a lot of assumptions -- notably that the only caller they ever have is the owner VI. You mess with this assumption at your peril, but it can be done.

I don't make any other assumptions than that the LabVIEW works the way it is documented :) Perhaps I've been using this feature for ages in development environment and now that I try to build an app, it doesn't work ;) Anyway I already reported this as a bug and I'm going to push towards this bug being fixed in the next release. I still think it's a bug without doubt. Language features that work in development environment should also work in the build applications. Nobody can deny this. Let's take shift registers for an example. The intended use is to preserve data from one loop iteration to the next. Then someone came up with functional globals. I guess it wasn't the intended use but it was an excellent use case. Should such apps build properly even though they are using shift registers in contrast to it's original intended use? I guess everyone agrees that these apps should still build properly. I think we are talking about similar issue here. Instance VIs are used as subVIs so far. But the language has allowed creating static VI references to instance VIs since LabVIEW 7 Express I guess. Creating instance VI static references doesn't require black magic or usage of any undocumented features; simply drop an Express VI on BD and then drag it to a static VI reference node. Maybe referring to instance VIs was not the intended usage, but I find it very useful. Should an incorrectly working builder optimization algorithm prevent me from using this language feature? Or should the builder bug be fixed? I'd like to hear other opinions here! Please be free to comment. I'll promise you all something extremely cool later on that takes advantage of this language feature...

As for when it comes to using reentrancy as a solution, yes it could work. However I think I need to use reentrancy parameter it its normal use cases. Otherwise it is a good suggestion.

Tomi

Link to comment

I strongly suggest that you not push this... because the fix is likely to be preventing instance VIs from being referenced through VI references entirely -- given that the design was that these VIs are purely behind the scenes and are designed to have only one caller, it is a bug that they're in the foreground at all. You mentioned only expecting stuff to work that is actually documented. Instance VIs aren't documented at all.

Link to comment

QUOTE(Aristos Queue @ Dec 10 2007, 05:00 AM)

I strongly suggest that you not push this... because the fix is likely to be preventing instance VIs from being referenced through VI references entirely -- given that the design was that these VIs are purely behind the scenes and are designed to have only one caller, it is a bug that they're in the foreground at all. You mentioned only expecting stuff to work that is actually documented. Instance VIs aren't documented at all.

I'm afraid I've already reported this issue and for technical reasons I cannot pull it back any more. :( I hope they are not going to close this hole. I guess it has been around since LV 7 and there is a large possibility that few of LabVIEW users are exploiting this hole. Closing the hole would also cause trouble to these customers.

Link to comment

I believe that being able to create a static VI reference to an instance VI "accidentally" happened in LV 8.5. It did not work in LV 8.2. You will likely need a config token from us to be able to create static VI refs to instance VIs in the next release. (It is not that we don't want somebody doing it when they mean to; it is that we don't want somebody accidentally doing it.)

I understand and empathize with your frustration. I cannot guarantee anything about future releases, but the code has already been written to improve instance VI behavior in several ways, including making static VI references to them work correctly in appbuilder. Additionally, no guarantees, but you should actually no longer even need the original instance VI call (which you currently have in a conditional disable node).

Like AQ expressed, instance VIs were originally designed to have exactly one subVI node caller, and every other use (including static VI refs to them) is a little wonky, but is being made more stable for internal reasons. The LabVIEW Statechart Module uses instance VIs heavily under the hood.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.