I am trying to build a plugin installer for my class based plugins. I have built plug-in architectures in the past but this is the first one using LVOOP based plugins.
I have read all about PPLs and Source Code Distributions in the forums and in several blog posts.
I have decided to take the Source Code Distribution (SCD) route for several reasons. I have applied all the tips, tricks and best practices from the information I have found but I am still having problems. I am hoping someone can tip me off to that one extra secret ingredient needed to make this work.
The problem I am having is when I attempt to load my plugin class from my EXE, I get:
Error 1498 occurred at Get LV Class Default Value.vi
LabVIEW: Library has errors. Fix the errors before attempting this operation.
Unfortunately, it does not give any specifics about what the issue is. These classes work fine in the DEV environment, so it is only when I call them from a EXE after they have been installed on my target machine that I see this error.
I have been very careful to include all the dependencies in the SCD and to exclude everything the EXE provides. I have also experimented with removing type defs, unused library member, etc. all with no effect.
Now the stranger part: a few of my plugins do load correctly. When I look at those, they are some basic examples I built first before making the more complex plugins. The one unique thing about them is they do not call any methods in the parent class (the top level class of all plugins that is provided in the EXE). I have created some methods in the parent class since then that do common jobs all plugins need. If I use one of these methods in one of the working plugins, it breaks in the EXE. But if I manually in-line the same code directly in the plugin then it loads fine in the EXE.
So, it appears that at least one of my problems is calling methods in the parent plugin class is a problem. I do not understand why this would be since the plugin must need the parent class to even be loaded by the EXE and therefore all of the methods in the parent class should be available for the plugin to call. Am I making the correct assumptions here?
If anyone has any ideas or a better checklist to follow to make this work, please let me know.
I have identified one method in the parent plugin class that seems to be causing some (maybe most) of the problems. This is a simple method that wraps up a few sub-vis so the plugin diagrams can be cleaner. Here is what I have tried so far:
1. If I copy the code in this method to a plugin's block diagram (manual in-line) then the plugin loads correctly.
2. If I set this method to in-line itself, and then call it from a plugin, the plugin fails to load.
3. I have tried deleting the offending method from the parent class and then recreating it from scratch and then using the new version in the plugins but they still fail to load.
4. I have tried renaming the parent plugin class to clear its mutation history.
5. I have changed the offending method to dynamic dispatch (even though there is no need for this) but that did not solve the issue.
6. I have eliminated any class property nodes from the offending method (had to do that to allow it to in-line) but that did not fix it either.
This is one of the strangest problems I have seen in LabVIEW in a while. I don't know what knob to turn next. I would rather not manually inline this code in every plugin since that would take a while to do and I would still not understand the issue. There seems to be no logical reason why this would not work. I can use other methods from the parent in a plugin and they load correctly. What is special about this one? And why would it matter if the code was in a sub-vi or on the block diagram directly? That should never make a difference!
are you using compiled libraries (lvlibp)?
No. I had intended to try PPLs but discovered that they will not work in my project because my plugins depend on classes in the EXE that are not in PPLs. I would have to re-architect and rewrite most of my application if I wanted to take the PPL route. So, I chose to do a source code distrubution based on the information I had gathered from various forum posts and blogs on the subject.
I've been able to use PPL in my code by building the parent class into a PPL, then use the parent class PPL in the source code for the application and the plugin (child class). This may not be as huge of a change as you believe.
I wish it was that simple. But, in my case, if I open a new project and just add the parent plugin class, it loads about 40 other classes into memory. My plugins are based off my messaging architecture used throughout my application. And my plugin parent has many common helper methods that all plugins use, but that also utilize several classes that my EXE also shares. It is not possible to unwind all this and switch to PPLs.
So PPLs are not the suspects. Would've been my guess, because I has stumbled over similar (not the same) problems when I switched over to PPLs
A little Off Topic: PPLs are a ccol thing if you consider using them right from the start. It's usually no joyride to just switch to PPLs during development. And even worse... there's no way back
I'm willing to bet it has everything to do with finding the functions that are embedded in the exe.
It's possible that it will work if the parent class is in the exe and the child classes in PPL (sorry, I have no experience with SCD, PPLs work great for everything I need) and you might be able to use the call parent method if needed. But how is a VI in SCD know the link changed when you pack the parent class into the exe? That would explain why your simple functions work since they are not trying to call anything from the parent class. It would also explain they your manual inline works but not the other methods you chose.
There's two ways I would go about trying to solve this:
1) I'd reconsider my architecture and understand why and it it was the best design to have the parent class within the exe. It's really not as difficult as you suggest to pull it out (and corrosponding classes) into it's own PPL (or SCD). A good design is to determine who calls a component, and if two different locations call into something, it makes sense to be seperate from those two locations. (PPLs work great on this). Good design upfront saves many undue weeks/months of debugging.
2) Ease into your debugging route. Use DETT to determine any unreported errors. Attempt to create the deployment on the dev computer to use debugging principles. Try enabling x10 option on your Get LV Class Default Value.vi. Etc. Or any other thing that can report the state of your code during execution.
"I won't be wronged. I won't be insulted. I won't be laid a-hand on. I don't do these things to other people, and I require the same from them." John Bernard Books
Thanks for the input.
Just to clear up a few things:
1. it is not possible to remove the parent plugin class from the EXE. The EXE needs this class so it can cast the dynamically loaded class to this type and be able to call methods in it.
2. By having the parent class in the EXE, the plugin does not need to 'find' it. It is already in memory and the plugin will just use it, regardless of where the plugin thinks the parent class should be located on disk. This is because a) I am not dynamically loading methods from the parent within the plugin and b) when a class is loaded into memory, all of its methods are loaded as well. And LabVIEW always uses the VI in memory before it tries to find it on disk.
Thanks for the tip on the 0x10 option setting. I had totally forgot I has set that to 0x20. After changing this, I found some code I had excluded from the plugin installer because I thought it was included in the EXE. Seems I overlooked a few items. As usual, the defect was between the keyboard and the chair... :-)
Now to see what other bugs I can find now that the plugins are loading!!
You CAN move the parent plugin class from the EXE -- by moving EVERYTHING out of the EXE except one wrapper VI that is nothing more than a launcher for the real top-level VI that is in the "everything that was in the EXE" PPL. I do strongly recommend you explore this option.