Jump to content

Calling VIs in main program from Dynamic VIs


Recommended Posts

Using the OpenG builder, I've been attempting to build a project that calls Dynamic VIs (my plugins). Each dynamic VI needs to call some VIs used in the main program. Is there any way to make dynamically loaded VIs call back to functions that are static VIs in the main application build? I've been getting Error 1003 when I try to do this, and it isn't an issue (as far as I can tell) with vi.lib files or anything like that, but rather the VIs called by my dynamic VIs that are part of my main program.

I would think about creating extra copies of the needed VIs or name mangling them with different names to create copies, but they need to be the same VIs because I'm using them for memory (non-initialized shift registers) as well as for the actual functions they perform.

Sorry if this is totally unclear, I've tried to be as clear as I know how. If you don't understand, ask questions and maybe I'll be able to give you a better explanation that answers your question.

Link to comment

I've been working on a similar project, but I haven't been trying to use VIs in my main application in my plugins. I ran into the same problem you have when I did try to do that. I ended up using a set of communication queue's to communicate information between the program and the plugins. Its really not that difficult, if you go ahead and document what the communication will be, and what each command will expect as an answer. I've got two queue's setup, one for commands, and one for data. I've got an independent loop in my main program that watches the communication queue for commands, then feeds data to the ones that need it, or simply acknowledges the command on the data queue.

Good luck, let me know if I wasn't clear enough here.

Link to comment

QUOTE(ars_stowers @ Apr 9 2007, 05:00 PM)

Using the OpenG builder, I've been attempting to build a project that calls Dynamic VIs (my plugins). Each dynamic VI needs to call some VIs used in the main program. Is there any way to make dynamically loaded VIs call back to functions that are static VIs in the main application build? I've been getting Error 1003 when I try to do this, and it isn't an issue (as far as I can tell) with vi.lib files or anything like that, but rather the VIs called by my dynamic VIs that are part of my main program.

I would think about creating extra copies of the needed VIs or name mangling them with different names to create copies, but they need to be the same VIs because I'm using them for memory (non-initialized shift registers) as well as for the actual functions they perform.

Sorry if this is totally unclear, I've tried to be as clear as I know how. If you don't understand, ask questions and maybe I'll be able to give you a better explanation that answers your question.

I am a bit confused.

Error 1003:

LabVIEW: The VI is not executable.

You mention that this happens with projects that use the OpenG Builder. I assume that this means that your program works in development mode, but not as an executable. Is this true? The error code seems to indicate otherwise. Have you checked all of your dynamic VIs to see that none of them are broke (broken run arrow)?

There should be no problems sharing VIs between normal and dynamic code. I have done this for many years.

Link to comment

Your description is unclear, but as a guess - When do you get the error?

If you're trying to use the Set Control Value and Run VI methods, I believe this won't work, since the VI is already reserved for running (like you can't press the run arrow on a VI that has a caller VI running).

What you should do instead is use the call by reference node.

If this doesn't help, you should post more details, like what you use the OpenG builder for, some diagrams of the systems or preferably some code. Also, does it work in the development environment?

Link to comment

QUOTE(chrisdavis @ Apr 9 2007, 07:56 PM)

I've been working on a similar project, but I haven't been trying to use VIs in my main application in my plugins. I ran into the same problem you have when I did try to do that. I ended up using a set of communication queue's to communicate information between the program and the plugins. Its really not that difficult, if you go ahead and document what the communication will be, and what each command will expect as an answer. I've got two queue's setup, one for commands, and one for data. I've got an independent loop in my main program that watches the communication queue for commands, then feeds data to the ones that need it, or simply acknowledges the command on the data queue.

Good luck, let me know if I wasn't clear enough here.

Simply because I have a fair amount of code to work with here, I would prefer not to change to a queueing system if possible. If I have to I will, but I think I will try to get working with what I have first. If that doesn't work though, I'll definitely come back to your solution.

Gleichman -

It does indeed work in development mode but breaks when built into an executable. Looking at my dynamic VIs, they are broken when I open them in the Built folder, but you have gotten me thinking that I was really stupid on this one.

I just copied all my dynamic VIs into my built folder and expected them to run. I knew they were broken, but figured if they were called by the program that had already loaded the VIs on which they were dependent, then the VIs they needed would already be in memory and they would not be broken as a result. I completely ignored the name mangling and directory issues that are bound to arise.

I'm rebuilding as I type, hoping that including the dynamic VIs as such in OpenG Builder rather than just copying will fix the issue. I'll let you guys know.

yen-

I get the error when I run the executable. It runs fine in development mode. I am using call by reference node rather than a method. I've attached the code to call my dynamic VIs. (sorry for the lack of comments. It's pretty simple, but if you get lost, ask and I'll explain. All my dynamic VIs ("modules") just have an error in and an error out. When the main selector is set to "run" or something like that (sorry, can't open the VI right now since I'm running a build), then you will get the code to run the modules. This VI is run at the rate I want to update my modules by a loop in the main program).

I'm not quite sure what you mean when you say "what you use the OpenG builder for." If you mean why, then the answer is that LV8.0.1 has some issues with nested libraries and I didn't want to lose the scoping capabilities of libraries just to use NIs builder. If you meant something else by your question, please rephrase it and I'll try to explain myself.

Thank you all for your help, it is greatly appreciated. Also, please don't laugh at the code as I'm a long way from being anywhere near good at LV.

After rebuilding (by the way, why does OpenG builder take so much longer to build stuff than NI's version?), the error at runtime changed to 1390 when attempting to load the dynamic VIs. This gives a 1026 (invalid reference) when trying to run.

1390=You attempted to open a VI Server reference to an out-of-scope VI. A VI can open VI Server references only to other VIs that it could call as subVIs. After the reference is opened, that VI can return the reference to other VIs that could not normally open the reference.

After building, I did have to reopen the library the dynamic VIs are members of and update it to change the files to reference the VIs I inculded dynamically in the build rather than the VIs in my dev project.

Sorry for just blabbering, I'll probably be able to give you all a better idea of what is going on if I look at it again fresh tomorrow morning.

Link to comment

QUOTE

After rebuilding (by the way, why does OpenG builder take so much longer to build stuff than NI's version?), the error at runtime changed to 1390 when attempting to load the dynamic VIs. This gives a 1026 (invalid reference) when trying to run.

I don't know the answer to this question, but I've thought it myself a couple of times. I don't mind it since I have SO much flexibility with the OpenG Builder that I can let it take a little longer to compile.

As for including your dynamic VIs in your built application... I've done this as well, and you don't end up with a true plugin system. Everytime you change an old plugin or make a new plugin, you have to recompile and redistribute your whole executable. You don't end up with a true "plugin" system, although I think you will find that your LV2 globals will work since everything is included inside a single exe. To create a true plugin system (see definition below) you'll have to use something besides a LV2 global to communicate and transfer data from plugins to main program, but you'll get the ability to expand the program without recompiling it. If you share your API set with others, you'll also have the ability to have other people expand your program to fit thier needs.

True Plugin System: A main executable program that can have additional functionality added at run time by adding a file to a known location (usually a directory underneath the EXE file in question) without having to recompile the executable. This type of architecture demands preplanning to provide a known documented API set to the developer of a plugin.

Link to comment

I use the plugin architecture and it is common that a plugin VI becomes broken (causing error 1003) in the run-time environement (RTE) because VIs in the development (DE) have been recompiled for some subtle reason, sometimes because a subVI has changed. So the plugin VI works well in DE but would need to be recompiled to be correctly linked to VIs in the RTE.

I have developped a technique to correctly compile/build plugin VIs to make them compatible with a built application but it may not work for LV >= 8. On the diagram of a VI I put the Top Level and Dynamic VIs (to include the whole hierarchy) of an executable. I do this using the Select a VI... dialog and typing the name of the VIs in the executable. Open the folder containing MyApp.exe and type in the file name MyApp.exe\MyApp.vi. Save this application loader VI. When you need to distribute a plugin, load this VI first then open your plugin VIs. That operation will recompiled the plugin VIs to make them compatible with the VIs in the application. However, if the plugin VI is still broken, that is probably because you made a change in the application VIs in DE that makes them incompatible with the previous version in the executable. After the plugin VIs are loaded, save them in a LLB using Save with Options...> Application Distribution.

If LV>=8 does not allow to select VIs in an executable to make the application loader VI, then you could save a snapshot of the application's hierachy in a separate LLB and load application VIs from there.

I'd like to see this functionality included in the OpenG Builder e.g. preloading fixed, compiled libraries of VIs and build the plugin with the RTE VIs rather than the DE VIs. I may work on this if I find time for OpenG development...

Link to comment

So I finally got things up and running. I'm still haven't figured out all the ins and outs of what is going on, but I'll be doing some more work on this.

Here is what I think I have figured out:

-Dyanamic VIs must be built when you build the executable so that they will link correctly to the VIs in the executable. This makes a plugin architecture without some other messaging system seem impossible per chrisdavis's explanation two posts up*.

-Adding the library VIs are a part of in addition to the VIs themselves as dynamic files in a build can screw stuff up (thus my scoping error). It is better to just add the VIs themselves and their library will be handled automatically.

-The library that is added dynamically screws up its associations so that it is linked to the DE VIs rather than the RTE VIs; this must be corrected manually.

-Don't forgot to change plugin VI names in your config file if their names have been mangled or else you will get an Error 7. :oops:

*It is actually possible to create plugins after an application has been built, and here is how. (After I figured this out, I read jpdrolet's post, and if I hadn't thought of this before, it may have encouraged me to think of it. I think our techniques are accomplishing the same thing, although in slightly different ways, unless I am misunderstanding how he said to do it, in which case our techniques are the same). The problem with plugins, as far as I can tell, is that they need to access the VIs inside of an executable file.

To create a plugin that uses VIs in an executable, we need a library of sorts with the executables VIs in it. To do this, we can just create a VI with all the static VIs that should be accessible to plugin writers and add said VI as a dynamic VI to our application build.

After the build, this VI can be opened, and any of the VIs in it copied into a library (drag and drop) to allow use as an API.

If I were to work on adding any functionality to the OpenG builder, it would be to automatically create a project with libraries in it containing links to all the VIs in the executable application on building.

Again, if this was a complete repeat of jpdrolet's post, I appologize for not understanding. Thanks for everyone's help though.

Link to comment

To make sure that plugins VIs are correctly linked to VIs within the executable, in DE I load the executable VIs directly from the application file .exe in and then load the plugin VIs. LabVIEW DE will relink the plugin VIs to the executable VIs. Then save plugin VIs to the location they have to be relative to the application .exe.

Look at the picture Load APP.vi includes VIs from the executable file itself. So loading the plugin VIs afterward wil link them correctly and they will be recompiled if needed. Then I save the plugin VIs in a LLB in the plugin directory of the application (\Modules) where they are expected to be.

http://forums.lavag.org/index.php?act=attach&type=post&id=5469

Link to comment

QUOTE(chrisdavis @ Apr 11 2007, 04:22 PM)

I hadn't heard and/or thought of this technique, very interesting option. Do you know if this technique would work in LV 8.2+?

If it doesn't work on LV8.2+ I guess you'd have to build another project with LLB instead of EXE. The improtant thing is to load a copy of the VIs as they are in the EXE because Vis in LabVIEW DE maybe modified in a way that will broke plugin VIs when loaded from the executable.

Link to comment

I forgot to mention that I am using LV 8.0.1

As far as I can tell, it is impossible to open a file within an *.exe from the open file dialog. The only way I have been able to get a RT VI into a plugin is to copy it directly from a dynamic VI built along side the executable. Can anyone confirm that this works in 8.2?

I'm currently working on comparing the binaries between plugin VIs to see if there is any good way to pull VIs out of executables to create an API.

jpdrolet-I don't think it will matter how we load the VIs from the executable, so long as the VIs we are loading are from the executable. Since I can't get your method to work, I'll have to stick with mine. Am I doing anything wrong by going to the BD, right clicking, selecting "Select a VI," navigating to the .exe's folder in the resulting dialog, then typing "MyApp.exe\VINAME.vi" in the file name box? Thanks.

Link to comment

I still don't understand the problem.

VIs can be dynamically called in an exe, in an LLB, or just in some directory as long as the correct path is supplied. For my "plug-in architecture", in development mode, I store my dynamically callled VIs in a dedicated sub directory. During program initialization, I read the filenames in this directory and open a VI ref to each one and store the refs in a USR. Then I use Call By Ref as necessary.

For my exes I roll my dynamic VIs into my exe. In the past I have left them out, but for various reason I now perfer to intergrate them in. The same VI that prefetches my VIs from the directory checks if the environment is exe and if it is it searches in the exe for files with a predifined prefix. I always use the same prefix for the dynamic VIs so the code doesn't change between Dev and exe.

- Alan

Link to comment

QUOTE(gleichman @ Apr 11 2007, 09:40 PM)

VIs can be dynamically called in an exe, in an LLB, or just in some directory as long as the correct path is supplied. For my "plug-in architecture", in development mode, I store my dynamically callled VIs in a dedicated sub directory.

...

For my exes I roll my dynamic VIs into my exe. In the past I have left them out, but for various reason I now perfer to intergrate them in.

If you can a VI in the run time environment that is not contained within the executable, you will be running that VI in a totally different execution environment, it will have no access to any of the VIs in your executable and must be built to run totally independent of the main executable. The type of plugin architecture you (and the original poster) are using bundle the plugins into the exe as dynamic VIs, which works fine, until you need to add or change plugin, at which time you will have to redistribute your exe file with the new/changed plugin.

It appears the original poster did not add his plugin VIs as dynamic VIs, based on what his later posts indicate. He has now added those VIs as dynamic VIs to his executable build and things are working for him.

Jpdrolet provided an alternate method of sharing VIs between the main executable and a plugin by linking the VIs you would like to share between the EXE and the plugin to the VI as it exists in the EXE. This could be a tedious manual process, depending on the number of plugins, so jpdrolet has suggested he would look at adding this capability to openG builder in the future. It is possible that this method will not work in LV 8.2+ because NI changed the built executable design from previous versions of LV.

Another alternative to communicating between plugin VIs and a main executable is to use a queue based messaging system to transfer messages and/or data. I currently use this method. I also build all of my plugins as LLB files that include all the VIs needed to run, including VIs from VI.lib, instr.lib, and user.lib, this gives me the capability to change a plugin, or add new plugins without rebuilding the main executable. This can be important if you want to distribute your executable to a large number of customers, while providing each customer a customized set of plugins. It also lets your users add plugins to your executable, without having the source code to your program.

Does this help?

Link to comment

QUOTE(gleichman @ Apr 11 2007, 10:40 PM)

I still don't understand the problem.

In therory that works but in practice, you have to make sure that VIs in DE don't change at all or else a plugin VIs may work in DE and be broken in RTE. I used to keep a "frozen" (read-only) copy of my project in a directory especially to develop plugins for a specific version of the application. Otherwise modifications in the project induced changes that break the plugins in RTE. For example, adding/removing/renaming a control in a global VI forces recompilation of all callers and a plugin linked to the new global VI will be broken in an application using a previous version, even if the plugin diagram is not affected by the change (yet another reason why globals are evil). Now I relink directly to the built app.

Link to comment

QUOTE(gleichman @ Apr 11 2007, 09:40 PM)

I still don't understand the problem.

VIs can be dynamically called in an exe, in an LLB, or just in some directory as long as the correct path is supplied. For my "plug-in architecture", in development mode, I store my dynamically callled VIs in a dedicated sub directory. During program initialization, I read the filenames in this directory and open a VI ref to each one and store the refs in a USR. Then I use Call By Ref as necessary.

For my exes I roll my dynamic VIs into my exe. In the past I have left them out, but for various reason I now perfer to intergrate them in. The same VI that prefetches my VIs from the directory checks if the environment is exe and if it is it searches in the exe for files with a predifined prefix. I always use the same prefix for the dynamic VIs so the code doesn't change between Dev and exe.

- Alan

Alan,

The problem I originally had was in trying to leave my dynamic VIs out of the executable so that they could be changed or new ones created after building the main executable. The problem that I was running into was that I could not link to the subVIs I needed in the executable from the dynamic VIs. Integrating the dynamic VIs would indeed have overcome my problem, but that would still leave me without the ability to change which dynamic VIs were loaded from a config file.

As chrisdavis has pointed out, I was having problems because I did not add my dynamic VIs to the executable build as dynamic VIs, so they were linking to the RTE subVIs. This was overcome by including them.

jrdrolet's assertion was that it is quite possible to create dynamic VIs that link to subVIs within the executable without having those dynamic VIs prepared at build time. From a plugin architecture standpoint, this is an extremely powerful tool.

Thank you all for your help; this discussion has been quite helpful and has gotten me thinking about how LabView actually does stuff.

-Aaron

Link to comment

I still don't understand the problem. You can dynamically call VIs outside of an executable. I've attached a simple example of this. The executable and the dynamic VI share a VI that is located in the exe. Example written in LV8.2.1.

http://forums.lavag.org/index.php?act=attach&type=post&id=5481

QUOTE(ars_stowers @ Apr 12 2007, 08:27 AM)

Alan,

The problem I originally had was in trying to leave my dynamic VIs out of the executable so that they could be changed or new ones created after building the main executable. The problem that I was running into was that I could not link to the subVIs I needed in the executable from the dynamic VIs. Integrating the dynamic VIs would indeed have overcome my problem, but that would still leave me without the ability to change which dynamic VIs were loaded from a config file.

As chrisdavis has pointed out, I was having problems because I did not add my dynamic VIs to the executable build as dynamic VIs, so they were linking to the RTE subVIs. This was overcome by including them.

jrdrolet's assertion was that it is quite possible to create dynamic VIs that link to subVIs within the executable without having those dynamic VIs prepared at build time. From a plugin architecture standpoint, this is an extremely powerful tool.

Thank you all for your help; this discussion has been quite helpful and has gotten me thinking about how LabView actually does stuff.

-Aaron

Link to comment

QUOTE(gleichman @ Apr 12 2007, 01:13 PM)

QUOTE(ars_stowers @ Apr 12 2007, 09:27 AM)

As chrisdavis has pointed out, I was having problems because I did not add my dynamic VIs to the executable build as dynamic VIs, so they were linking to the RTE subVIs. This was overcome by including them.

My problem was that I was trying to dynamically call VIs not included as dynamic VIs in the build. Help from everyone in this discussion and fiddling around on my own helped me figure this out.

The discussion shifted from there to the best way to design a plugin architecture to allow linking to the VIs in the executable by VIs not included as dynamic VIs at build time.

I would have looked at your files, but unfortunately, I am stuck at 8.0.1 and can't open them.

Hope that explains it better and sorry for being unclear in the beginning.

Link to comment

I don't think what Chris is saying is true. My example calls a VI that is NOT in the exe. I have down converted it to 8.0.

http://forums.lavag.org/index.php?act=attach&type=post&id=5482

QUOTE(ars_stowers @ Apr 12 2007, 01:34 PM)

My problem was that I was trying to dynamically call VIs not included as dynamic VIs in the build. Help from everyone in this discussion and fiddling around on my own helped me figure this out.

The discussion shifted from there to the best way to design a plugin architecture to allow linking to the VIs in the executable by VIs not included as dynamic VIs at build time.

I would have looked at your files, but unfortunately, I am stuck at 8.0.1 and can't open them.

Hope that explains it better and sorry for being unclear in the beginning.

Link to comment

QUOTE(gleichman @ Apr 12 2007, 02:47 PM)

This is absolutly right. There is no problem per se with calling VIs anywhere on the disk even in an executable. There are however some restrictions as to what such VIs need to conform too.

1) For the runtime system the VIs should have been compiled in the same LabVIEW version (bugfix version number differences are normally ok) and for the same platform.

2) You need to construct the path to those VIs exactly in order to be able to call/load them.

3) If they make use of SubVIs those subVIs MAY NOT clash in any way with subVIs that are used in the main executable already. Either you make sure they use a completely different hierarchy of subVIs (name prefixing for instance or LabVIEW names spaces in >= 8.0) or you make sure those subVIs are all exactly the same for the plugins as for the main executable.

Number 2 is the first stumble block most people fall over. And once they figure that out they immediately run into 3, which can only be solved with a strong discipline while developping. I usually do that by having a Top Level VI which includes all Top level VIs of my project including the plugins and make sure to recompile the entire project before making a distribution of the executable and/or plugin component.

Rolf Kalbermatter

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.