LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How to use VIs as plug-ins ?

My app is going to use a "plug-in" architecture.

By that I mean that the finished EXE will look for any *.VI files in a certain directory. If the config file says to use ABC.vi on channel 13, then I want to load ABC.vi from this directory and execute it.

Inputs and outputs for these plug-ins will be thru a global function, not thru terminals.

Speed performance is an issue, and they will be called many times during a test, and will likely be small calculations.

So if a test calls for three VIs, I want to load them all at the start of the test, execute them during the test, and unload them all at the end.

Looking thru the VI SERVER stuff - I see two choices:
OPEN VI REFERENCE - CALL BY REFERENCE - CLOSE VI REFERENC
E
or
OPEN VI REFERENCE - INVOKE METHOD (Run VI) - CLOSE VI REFERENCE


Why should I choose one method over the other?

Does OPEN VI REFERENCE amount to "LOAD THIS VI AND GET READY TO RUN" ?
(Assuming I have only one reference to it)

Does CLOSE VI REFERENCE amount to "UNLOAD THIS VI AND RE-CLAIM the MEMORY" ?
(Assuming I have only one reference to it)

I'm thinking of OPENING VI REFERENCES at the start of test, stashing the reference numbers somewhere( associated with the channel they belong to), and using CALL BY REFERENCE or INVOKE METHOD(RunVI) to execute them.

Is that the best way?


Any problems because of an executable (.exe) dynamically using .VI files?
Steve Bird
Culverson Software - Elegant software that is a pleasure to use.
Culverson.com


LinkedIn

Blog for (mostly LabVIEW) programmers: Tips And Tricks

0 Kudos
Message 1 of 11
(4,039 Views)
Plugin architectures take a bit of planning and rigor, but they are very
flexible and extensible.

> Inputs and outputs for these plug-ins will be thru a global
> function, not thru terminals.

This can work, but be careful of race conditions. If you have multiple
VIs trying to read/modify/write an array, then these accesses need to be
protected, otherwise, you can lose values. There is more on this in a
Dr. VI article, and this doesn't really have anything to do with plug-in
architectures, but instead on globals that can be written to at multiple
locations in a app.

> Speed performance is an issue, and they will be called many times
> during a test, and will likely be small calculations.
>
> So if a test calls for three VIs, I want to load them all at the
> start of the test, execute them during the test, and unload them all
> at the end.
>
> Looking thru the VI SERVER stuff - I see two choices:
> OPEN VI REFERENCE - CALL BY REFERENCE - CLOSE VI REFERENCE
> or
> OPEN VI REFERENCE - INVOKE METHOD (Run VI) - CLOSE VI REFERENCE
>
>
> Why should I choose one method over the other?

Call is similar to a subVI call. The call by reference node knows the
input and output types and it is actually pretty easy to pass
parameters. The call node will not return until the subVI completes,
thus the calling diagram will be synchronized to the call.

Run VI method is closer to pushing the Run button on a VI. It doesn't
allow for parameters to be passed, but it allows for VIs with different
connector panes to be invoked. It also allows for the Run to either
wait for and synchronize with the called VI, or to return as soon as the
VI starts, letting each run to completion in parallel.

In short, both have their place. The first is a subVI call where you
get to specify which of several subVIs to call. The second is good for
spawning a child process to do a search, report, etc. especially when
you don't care about the results.

Be sure to look at the examples that use these as te opens differ in
that the Call requires a strict connector specification and the Run
doesn't need it.

> Does OPEN VI REFERENCE amount to "LOAD THIS VI AND GET READY TO RUN" ?
> (Assuming I have only one reference to it)
>
> Does CLOSE VI REFERENCE amount to "UNLOAD THIS VI AND RE-CLAIM the
> MEMORY" ?
> (Assuming I have only one reference to it)

Yes, Open means load if necessary and give me a reference. Close means
unload and invalidate the reference.

> I'm thinking of OPENING VI REFERENCES at the start of test, stashing
> the reference numbers somewhere( associated with the channel they
> belong to), and using CALL BY REFERENCE or INVOKE METHOD(RunVI) to
> execute them.
>
> Is that the best way?

It depends on performance versus memory usage. Loading and unloading
can a significant amount of time, so loading and reusing the reference
before closing it is a good idea. Whether to load at launchtime, load
when needed and have a timer to purge the loaded VIs, loading and
unloading at certain stages of execution, or loading and unloading for
each call requires more information about the project, and they may be
hard to choose between without some experimentation.

> Any problems because of an executable (.exe) dynamically using .VI
> files?

LV has the compiler and Open Reference can recompile older VIs if
necessary. An EXE can't compile VIs. This simply means the plug-ins
have to be saved in a compatible version or they will not work. The
definition of compatible is more flexible for the editor than for an EXE.

Greg McKaskle
0 Kudos
Message 2 of 11
(4,038 Views)
Some words to your global variable data exchange: One way to prevent race conditions and additional temporary copies of your global data is the 'good old Labview 2 style global'.

However, for your application (functions.vis as addins) I would spend some more thoughts on the data definitions and use the Call by reference with fixed terminals. At last you can make a speed test with x calls in a loop with a global variable approach and compare it with a terminal based Call by reference ( with a variant in- and output and all nessesary data extraction if needed).

Regards
Henrik
Greetings from Germany
Henrik

LV since v3.1

“ground” is a convenient fantasy

'˙˙˙˙uıɐƃɐ lɐıp puɐ °06 ǝuoɥd ɹnoʎ uɹnʇ ǝsɐǝld 'ʎɹɐuıƃɐɯı sı pǝlɐıp ǝʌɐɥ noʎ ɹǝqɯnu ǝɥʇ'


0 Kudos
Message 3 of 11
(4,038 Views)
Well, yes, that's why I said that I would use GLOBAL FUNCTIONS. The plug-in VI will call a function to request a value, crunch, crunch, then call the function to store the result value.

I can't use terminals because I do not know what data the plug-in wants. One plug-in might convert channel 13 from Fahrenheit to Celsius. Another might take Pressure from channel 2, Temperature from channel 23, and RPM from channel 65 and produce Horsepower on a new channel 99 - That's up to the plug-in writer.

I don't know what you mean by comparing the "global variable approach" to a "Call by reference approach".

I want to compare the CALL BY REFERENCE approach to the INVOKE METHOD (Run VI) approach. It will use the global function to get and set d
ata , either way.

I am hoping someone can tell me the pros and cons of one way of CALLING the thing over the other.
Steve Bird
Culverson Software - Elegant software that is a pleasure to use.
Culverson.com


LinkedIn

Blog for (mostly LabVIEW) programmers: Tips And Tricks

0 Kudos
Message 4 of 11
(4,038 Views)
Have just spent ages writing an application that uses plug in modules, loads
modules as found from the registry. Can load modules with any input/output
pattern using variant data. Can also load multiple levels of modules, i.e.
a module can load sub-modules.

If you want i can send you the top-level application which does all the
calling and management. It is tailored to my application but could be
adapted. Please post your email here if you want it.
0 Kudos
Message 5 of 11
(4,038 Views)
this doesn't really have anything to do with plug-in architectures, but instead on globals that can be written to at multiple locations in a app.

--- I'm aware of the potential problems of globals, I will use a global FUNCTION to store / retrieve data.


Call is similar to a subVI call.� The call by reference node knows the input and output types and it is actually pretty easy to pass parameters.� The call node will not return until the subVI completes, thus the calling diagram will be synchronized to the call.

--- I cannot use terminals to pass data, as I do not know what data the plug-in wants. One plug-in might need a value from one channel, another might need values from 5 or more. Who knows, another might need to average all 27 temperature channels.
So the terminal will be fixed (probably one unused terminal), regardless of which mthod is used to call.



Run VI method is closer to pushing the Run button on a VI.� It doesn't allow for parameters to be passed, but it allows for VIs with different
connector panes to be invoked.� It also allows for the Run to either wait for and synchronize with the called VI, or to return as soon as the VI starts, letting each run to completion in parallel.


--- They will all have the same (unused) connector pane, so that is not an issue, either way.

I will have to wait for completion, since it's possible that the next channel's inputs are this channel's outputs, so I have to keep it synchronized either way.

Therefore, given the way I'm going to use it, I don't see a difference between CALL BY REFERENCE and INVOKE METHOD. So I will flip a coin.



Whether to load at launchtime, load when needed and have a timer to purge the loaded VIs, loading and unloading at certain stages of execution, or loading and unloading for each call requires more information about the project, and they may be hard to choose between without some experimentation.


--- Well, I will have a START TEST button, and a CONFIGURE button. In the CONFIGURE screen, they will choose what VI's get plugged in where. When they start the test, I will load the plug-ins, and complain if they can't be found or something. During the test they will be called, and when the test is over they will be unloaded.



LV has the compiler and Open Reference can recompile older VIs if necessary.� An EXE can't compile VIs.� This simply means the plug-ins
have to be saved in a compatible version or they will not work.� The definition of compatible is more flexible for the editor than for an EXE.


--- That I hadn't thought of, but it makes sense. So if they upgrade the run-time from 6.1 to 7, they will manually have to re-compile all the plug-ins (mass compile). That may or may not be true for 7 to 7.1, I guess.

Steve Bird
Culverson Software - Elegant software that is a pleasure to use.
Culverson.com


LinkedIn

Blog for (mostly LabVIEW) programmers: Tips And Tricks

0 Kudos
Message 6 of 11
(4,038 Views)
Well, thanks, but really I just wanted an answer to which way to call it. I already have the innards worked out.
Steve Bird
Culverson Software - Elegant software that is a pleasure to use.
Culverson.com


LinkedIn

Blog for (mostly LabVIEW) programmers: Tips And Tricks

0 Kudos
Message 7 of 11
(4,037 Views)
> --- Well, I will have a START TEST button, and a CONFIGURE button. In
> the CONFIGURE screen, they will choose what VI's get plugged in where.
> When they start the test, I will load the plug-ins, and complain if
> they can't be found or something. During the test they will be
> called, and when the test is over they will be unloaded.


>
> LV has the compiler and Open Reference can recompile older VIs if
> necessary. An EXE can't compile VIs. This simply means the plug-ins
> have to be saved in a compatible version or they will not work. The
> definition of compatible is more flexible for the editor than for an
> EXE.

>
> --- That I hadn't thought of, but it makes sense. So if they upgrade
> the run-time from 6.1 to 7, they wi
ll manually have to re-compile all
> the plug-ins (mass compile). That may or may not be true for 7 to
> 7.1, I guess.

Actually, the runtime versions can coexist. This means that this would
fall out of date only when you update your EXE, or more likely, when the
user builds new plug-ins in a newer version. To determine compatibility
without recompile, you basically see that the first two digits match.
Thus, 7.0 and 7.1 will not be combatible without a recompile, 7.0 and
7.0x will be. At least this has been the system for many many years.

Greg McKaskle

0 Kudos
Message 8 of 11
(4,037 Views)
Hi Tom,

I'm just about to spend ages designing such a plugin structure too! If I can talk you into sending me your top level, for inspiration and help, I would definately owe you a beer or two!
My email adress is dg@mediascape.dk

Thanks in advance.
0 Kudos
Message 9 of 11
(4,037 Views)
Hi,

The behaviour you are describing is exactly one of the pillars with object-orientation, GOOP, that is called dynamic binding. That is, in run-time, to decide which LabVIEW code to run.

The benefit of using an object-oriented design is that there are rules and you do not have to reinvent the wheel over and over again to create an application with dynamic behavior.

To achive a plug-in architecure as bescribed above. You simply design a generic base class and declare all methods (VIs) as virtual. Then you might reimplement them in a subclass and dynamically call the correct implementation at run-time.

All this behaviour is supported by the new GOOP Inheritance Tool. Please visit:
http://www.endevo.se/default.asp?lang=eng
and click on products.

There you might download examples, presentations, white papers and demos to fully describe the toolkit.

To relate to the specific problem in this question, is that this new GOOP Toolkit uses strictly-type VI server to implement the dynamic behaviour. The GOOP kernel stores and handles all VI server references and the user of the toolkit does not have to handle this at all, everything is taking care of. The developer only have to bother about the behaviour, not technical details like reference handling etc.

Regards,
Mattias Ericsson
Endevo Sweden
Main developer of the GOOP Inheritance Toolkit
0 Kudos
Message 10 of 11
(4,037 Views)