Imagine you’re testing a system that has a long startup time, and you find a small change that needs to be made. Now you have to make the software change, rebuild the executable, shut down the application, deploy the new executable, and go through the long startup period again. What a waste of time! Wouldn’t it be great if you could avoid having to stop and restart the entire application? It would be like refueling in flight. Well, now you can.
I attended the US Certified LabVIEWTM Architect (US CLA) Summit in Austin this past spring. After Steve Ball, Lead LabVIEW Engineer at Nuvera Fuel Cells, gave a presentation called Packed Project Library Pointers Framework Edition, I had an epiphany. With encouragement from Omar Mussa, Director of Software Engineering at EUV Tech, and Jeff DeBuhr, Sr.Test Engineer at Tecnova, I decided to pursue my idea.
By using Packed Project Libraries (PPL) I now can build software components that can be changed while a LabVIEW application is still running. I built a sequencer application that allows a user to select a particular piece of code or step to run. While the application is running, a developer can change that particular step’s code and rebuilds the PPL. If the user runs the same step again, the new code is used. Now let’s see this in action.
The first thing we do is launch the application and run the startup step.
Then we run Test1, but it fails.
So we look at the code for Test1 and realize all we have to do to make the test pass is change the message text to say Test1 passed. Don’t you wish it was always that easy?
To deploy this change we could run the shutdown step, deploy the change, run the long startup step, and then run the Test1 step. Or, for a much simpler approach, we can instead just make the software change and build the PPL while the application is still running.
We run Test1 again and we have a passing test.
Now let’s look at the code that is called when we press the Run Step button. As you can see the PPL file path is an input. I decided to not show it on the front panel so I could keep the user interface clean for demonstration purposes. This path could be locally stored or on the network. We strip off the name of the PPL and use it to find the path of the Run Step.vi and LabVIEW (LV) Class that will be run. The Run Step.vi is dynamically run using VI Server. Using VI Server is an important part of the solution. The LV Class Path is an input into the Run Step.vi. The message displayed on the front of the application is updated when the Run Step.vi has finished.
The Run Step.vi calls one of the children of the step class using the factory pattern.
This approach has some advantages, but there are some design constraints to consider. The code for the PPL must reside in a different LV project from the calling VI. LabVIEW will return an error if you try to build a PPL while that same PPL is in memory in another open project. This means that my approach of making changes and rebuilding the PPL while the application is running only works if the application is an executable.
Another consideration is related to making changes to LV classes inside of the PPL. If you change code inside of a LV class in a PPL, then that change will not be reflected in run-time if that LV class is in memory. So that begs the question, how do you know if the LV class is in memory or not when you make the change to the PPL?
As Stephen Loftus-Mercer, Senior Software Engineer in LabVIEW R&D explained:
"The only way that a class is able to leave memory is when we detect that all of the VIs using that class are all idle and are themselves leaving memory. Any VI using a parent class counts as a use of all of that parent's child classes. So you simply have to make the caller VI go idle and then unload that."
He also clarified that the reason he has said
“There's no way to unload plug-ins is that people who want to do this generally mean I want to leave the framework running but unload a specific plug-in. The unloading described here only works if you halt and unload the whole framework."
This is why I chose to use VI Server to call the Run Step.vi and did not call the LV class code directly in the block diagram of my application.
In my example, I am unloading the entire framework, i.e the Run Step.vi. The key here is that you have to be aware of memory management with LV classes. This becomes more difficult with more complex class hierarchies. One approach suggested by Omar Mussa is that you could make a LV class manager to keep track of which classes are in memory. You could then remove a particular class from memory by sending a message to that class to shut itself down or having the class monitor for changes to the PPL on disk and then shut itself down.
In summary, by using a PPL and VI Server, I was able to make changes to my built application without having to stop the application. When deciding whether to implement this approach you should weigh the time it saves making changes during run-time against the increase in development time. The additional development time efforts include creating multiple projects, building the main application into an executable, and designing around memory management of LV classes.
I would like to thank everyone in the LabVIEW Community and at G Systems for their help. The CLA Summit was a big catalyst in my development of this approach. I also would like to thank Jon McBee for inviting me to be a guest writer on his blog. I am excited to see others’ thoughts and comments.
Russell Blake is a Senior Program Manager at G Systems L.P. He is a Certified LabVIEW Architect and National Instruments Certified Professional Instructor with 15 years of industry experience. He holds a Bachelor of Science in Electrical Engineering from The University of Texas at Austin and a Master in Science in Engineering Management from Southern Methodist University.
© Copyright 2016 G Systems L.P.