LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Build Specification does not include VI which is part of a "always include" .lvlib

We have an application built into an executable with a plug-in class architecture, where the plug-in classes are dynamically loaded at runtime from source distributions. The application and all its plug-ins are built separately. All additional build exclusions are turned off.

 

One of our plug-in classes in turn dynamically loads a VI (which is part of the class itself), which in turn uses a SubVI that is part of a library included in the build of the main application (by setting the library to always included in the source files), e.g. Library.lvlib:SubVI.vi. The main application itself does not use this specific SubVI itself, but we want it to be available for the plug-ins. According to the LV 2016 documentation, setting a library to always included will mark all members of the library as referenced, so we don't set the Library.lvlib:SubVI.vi to be always included explicitly in the source files. According to its source file settings, it is set to "Include if referenced". The plug-in source distribution in question has the library set to "always exclude".

 

However, loading the VI fails (error 1003) as long as the VI includes a call to Library.lvlib:SubVI.vi.

So far, the only way we found to fix this is to move this specific SubVI from its library to the same class that includes its caller.

 

It seems to us that LV simply does not include Library.lvlib:SubVI.vi in the main application build for some reason.

Is this possible, or are we running into an issue due to the complex setup (a dynamically loaded class dynamically loading one of its member VIs that in turn calls a VI that is part of a library included in the main application)?

0 Kudos
Message 1 of 9
(5,080 Views)

You don't have the "Remove unused members of project libraries" option ticked by chance? http://zone.ni.com/reference/en-XX/help/371361L-01/lvdialog/additional_exclusions/. When including Library.lvlib into your exe this option enabled would remove any members that are not statically linked ("called on a block diagram"). 

 

Although classes are a special kind of project library, this option does not affect them.

0 Kudos
Message 2 of 9
(5,031 Views)

No, this option is for sure not ticked.

When an lvlib is marked as "always include", its members are not. Although this should not be an issue according to the LV 2016 manual, because all its members are marked as referenced, we even tried also marking the VI in question as "always include". Unfortunately this still does not solve the issue.

 

I've created a minimal example to showcase the issue, which I have attached to this post.

Simply use the builds or build them yourself, run the exe, browse for the plugin.lvclass source distribution and click load. The application stops with error 1498.

 

If you now exclude main.lvlib:lib_test_1.vi in plugin.lvclass:Get Class Name.vi, build the plugin, and try to load it, it works.

 

If you include main.lvlib:lib_test_1.vi in plugin.lvclass:Get Class Name.vi again, and also include the same VI in main.lvclass:Get Class Name.vi and build the plugin and exe, and try to load it, it works. The same is true if the main.vi includes main.lvlib:lib_test_1.vi.

 

To us, this points to an issue with LV not including all members of main.lvlib although it should.

0 Kudos
Message 3 of 9
(5,000 Views)

The forum managed to delete my post before I was finished. But I see your problem(s). Before the post gets accidentally removed again:

 

Your plugin source is all marked with separated compiled code. Your exe only hosts the run-time engine and will not be able to load the class or VIs since there is no object code present (all in the IDEs cache). You can confirm that this is also the case with your source distribution - when your main.exe is running, try using "Open" in the menu to actually open the Get Class Name method of your distribution from disk. LabVIEW tells you that the plug-in source has no compiled code. Correcting this allows the plug-in to appear to load without error.

1.png

 

 

Message 4 of 9
(4,974 Views)

Since that got posted ok, here is the second issue I found.

  • When you build an application, project libraries get namespaced (eg. main.exe:main.lvlib:main.vi). So, as far as LV is concerned, the main.lvlib in your exe is a new project library and totally different to the original.
  • Your plug-in is a source distribution, which is really just a fancy name for exporting a cleaner version of your code. Your plugin therefore still references the same statically linked project library on disk that is used to (by path even).
  • When you load your plugin in your main.exe it actually loads the original source copy in from disk. You can tell this from these screenshot where, prior to loading the plug-in for the first time, I deliberately renamed the "main" folder on disk to "main2" so that the absolute path would no longer be the same. As you can see it can no longer load the plugin:
  • 2.png 

Whether this is a problem for you depends on the scope of your project and whether you want the plug-in to be able to access any run-time information from VIs, variables etc. from the run-time main.exe:main.lvlib.

Message 5 of 9
(4,972 Views)

Thanks a lot for pointing this out tyk007! We already discussed this as a possibility, but excluded it because we thought that the compiled code would always be there for executables. Unfortunately, there is also no option to explicitly set to include the compiled code as there is for source distributions. Also, we were really hoping that separating the compiled code from the source would not be the issue, since we're using SVN for version control and it is really annoying that VIs "change" just by opening them.

 

We're just testing the original project with the new settings to see if that solves the issue.

 

Regarding your point with the namespacing: I see what you mean, and we're just trying to understand why we didn't see this exact issue before. Possibly because our executable has dynamically loaded classes "built-in", but this is a very good point which we will investigate further. Thanks a lot!

0 Kudos
Message 6 of 9
(4,961 Views)

@KeA wrote:

 

Regarding your point with the namespacing: I see what you mean, and we're just trying to understand why we didn't see this exact issue before. Possibly because our executable has dynamically loaded classes "built-in", but this is a very good point which we will investigate further. Thanks a lot!


We just investigated this further, and you're completely right - we would most likely run into this issue next 😉

From what we could gather, it looks like the namespace stays the same, but the location from where the library gets loaded changes for the exe and the source distribution. We came to this conclusion because if we somehow make sure that the SubVI from main.lvlib is loaded into memory by the exe before the plugin (no matter if it is done by static or dynamic linking), the plugin loads just fine.

0 Kudos
Message 7 of 9
(4,953 Views)

A lot of people use packed project libraries (PPL for short) as plug-ins. They have the advantage of being purely compiled code (ie are not decompilable). The biggest disadvantage is that they are compiled for a specific version of LabVIEW which can be a pain for maintainability as LV version increase; you would need to keep rebuilding.

Message 8 of 9
(4,944 Views)

I played around with a toy example (simple FGV in a library) while monitoring the exe Win32 API calls and I think you are right. It looks like as long as LV can find the contents on disk it can load them but doesn't allocate new memory - they are already in memory. I recall struggling with something similar years back but now I'm not quite sure where that idea of mine came from, lets put it down to old age for now.

 

But it does highlight that there are some almost hidden dependencies not just in memory but on disk with this solution. It would certainly require a level of vigilance. The best suggestion I can think of is to expose the interface seperately from the exe and plugins. That way the plugins and exe are not dependent on each other in any way. The exe can simply load the interface class into memory dynamically first so that it knows how all the plugins will conform.

Message 9 of 9
(4,937 Views)