From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

debugging a factory pattern LVOOP plugin

When the executable runs, you could try to drop a class VI on the executable (or use the command line "exe_name.exe "path to VI""). The executable will (try to) open the VI. If it's broken, the error might give you more information, ideally even a reason...

0 Kudos
Message 11 of 34
(757 Views)

Sounds like your plugin class cannot find its parent class when being called from an exe. I havent worked with source distributions much, can you write some code to find out where the source distribution version of your class thinks its parent class is? I am assuming your parent class is included in your main .exe? Could it be a loading conflict? The source distribution thinks its parent class will be at one location, and it is already loaded from somewhere else?

0 Kudos
Message 12 of 34
(750 Views)

Hmm, sounds like a problem we had with a similar outsourcing of VIs.  The problem may be completely unrelated to LVOOP.

 

There's a difference between having a file included in a build and having it loaded in memory when needed.  Placing a constant on a BD will ensure the associated definitions are loaded into memory when the program is running, simply including the file and not referencing it will not (And the parent class will not be found when you try to load a child).

0 Kudos
Message 13 of 34
(746 Views)

Thanks for the suggestion. I hadn't thought of that. I would suppose that when you do this, the RTE would try to open the VI that you drop on it first, then run the VI, right?

So: I created a version of my .exe that did NOT work. E.g. by leaving out the parent class constant on the diagram before building it, it fails. Then I dropped the parent class onto the .exe. It still failed. Whereas if I include the parent class constant on the diagram before building, it works...

I'm not quite sure what this means.

-------------------------------------------------------------
David Thomson Original Code Consulting
www.originalcode.com
National Instruments Alliance Program Member
Certified LabVIEW Architect
Certified Embedded Systems Developer
-------------------------------------------------------------
There are 10 kinds of people: those who understand binary, and those who don't.
0 Kudos
Message 14 of 34
(734 Views)

Paul, I suspect you are pretty close to the mark, that it's a loading problem with some subtle conflict. Still haven't been able to figure out the details.

Intaris, can you expound any further on this difference? I've seen the evidence that what you say is true, but I still don't understand it. I've use the "Always Include" in an .exe before to ensure that VI's were available to the .exe when they were needed to load something dynamically at run time. And it has worked before. So I assumed that this put them "in memory". Which, frankly, I think they are. If they are part of the .exe and the .exe loads into memory to run, they are probably technically in memory. But maybe they have not yet been loaded into the call chain until the dynamic run function is executed. Then LV tries to find all the dependencies. This is probably where something is conflicting between what is in the .exe and what the plug-in is looking for...

-------------------------------------------------------------
David Thomson Original Code Consulting
www.originalcode.com
National Instruments Alliance Program Member
Certified LabVIEW Architect
Certified Embedded Systems Developer
-------------------------------------------------------------
There are 10 kinds of people: those who understand binary, and those who don't.
0 Kudos
Message 15 of 34
(731 Views)

@Dave_Thomson wrote:

Paul, I suspect you are pretty close to the mark, that it's a loading problem with some subtle conflict. Still haven't been able to figure out the details.

Intaris, can you expound any further on this difference? I've seen the evidence that what you say is true, but I still don't understand it. I've use the "Always Include" in an .exe before to ensure that VI's were available to the .exe when they were needed to load something dynamically at run time. And it has worked before. So I assumed that this put them "in memory". Which, frankly, I think they are. If they are part of the .exe and the .exe loads into memory to run, they are probably technically in memory. But maybe they have not yet been loaded into the call chain until the dynamic run function is executed. Then LV tries to find all the dependencies. This is probably where something is conflicting between what is in the .exe and what the plug-in is looking for...


Just because something is in the exe, doesnt mean its 'in memory.' One way to test this - use the 'Get LV Class Default Value By Name' on your parent class in the exe - if it returns an error, the class isnt in memory (or has some other issue.) Do this where you are trying to open your plugins. If the class is in memory, that function should work. So, if your parent class isn't in memory when you try and load the child, and its parent isnt where it thinks it will be, you could get the error you are seeing. 

0 Kudos
Message 16 of 34
(727 Views)

@Dave_Thomson wrote: So I assumed that this put them "in memory". Which, frankly, I think they are.

Nope.  Think of the exe as a zipped folder.  Only the top-level VI(s) get loaded and bring any static dependencies with them.  Anything else sits on disk until explicitly called.  Placing the constant on the BD forces the class definition into the dependencies and it gets loaded with the top-level VI.  There's no magic involved.

0 Kudos
Message 17 of 34
(721 Views)

I wonder what I said that made you think that I believed there was magic involved?      😉

 

I certainly do not know this from having learned it as a fact, but the picture in my mind of how an exe is loaded is that the entire thing is read off disk when it is run, then it is executed. Frankly, it would seem unlikely that it is that simple in Windows. But the test I did suggests that this is closer to reality than the disk-based zip file model.

I wrote a VI that sits in a loop doing nothing until you press a button. Once the button is pressed, it dynamically calls a VI that causes the computer to beep. Simple enough. Works in source code.

So I built it into an .exe. The first time without including the dynamically called VI in the build. (E.g I did NOT use the Always Include option to add the dynamic VI.) Of course, it didn't beep when the button is pressed.

Then I built it into an .exe and DID include the dynamic VI in the "Always Include" section. Gratifyingly, it beeped when you press the button.

So then I copied the second .exe to a thumb drive, rebooted the computer to ensure that nothing was hanging around unintentionally in memory, and launched the .exe from the thumb drive. While the .exe was sitting in its loop waiting, I pulled the thumb drive out of the computer. The .exe file is now inaccessible. But when you push the button, the program still beeps. E.g. the dynamically-called VI appears to have been loaded into memory when the .exe was first run, not when it was later called when the button was pressed.

I'm guessing, though I don't really know, that there are "levels" of loading. From Window's perspective, the dynamically called VI is loaded when the .exe is run. But that doesn't mean that the LV run time engine has actively linked that VI to the code that is running. E.g. yes, it is in RAM, but no, it isn't "in memory" from LabVIEW's perspective. At least, not in the memory that LV defines as the active program.

I've attached a zip of the project here in case anyone wants to test it.

It might be interesting to have NI comment on this whole issue, about where things are held when they are not "loaded" by LV. Also, could it be different for classes than for "normal" VI's?

 

Cheers,

     DaveT

-------------------------------------------------------------
David Thomson Original Code Consulting
www.originalcode.com
National Instruments Alliance Program Member
Certified LabVIEW Architect
Certified Embedded Systems Developer
-------------------------------------------------------------
There are 10 kinds of people: those who understand binary, and those who don't.
0 Kudos
Message 18 of 34
(687 Views)

I think you are correct in that when you run an .exe everything is 'opened', but that doesn't mean its 'in memory'. I do think the disk based model is correct - I linked an article below, but I know there are some more comprehensive ones out there, I just couldn't find them. 

 

Note that you're supplying the path to the VI in your test code - try it again with just the VI name and you will see the problem - it runs in development, but when you build it, you get an error at the open VI reference, because the VI isnt in memory. Throw the VI on the block diagram and use the VI name, and you will not see an error at the open VI reference (you get an error from the invoke node, but the VI reference was still able to be loaded.)

 

I dont think this is any different for VIs or classes. If your beep VI had a dependency it was expecting at some location and cannot find it, you would get an error when you try and load it dynamically. Did you try the experiment I suggested with loading the parent class by name? 

 

http://zone.ni.com/reference/en-XX/help/371361L-01/lvconcepts/referencing_files_in_applications/

0 Kudos
Message 19 of 34
(671 Views)

Paul,

     Thanks for the link. I do understand that LV uses (or at least, used to use) a zip file-like structure for storing VI's inside the .exe. That doesn't mean that it leaves all that content on disk until it is called.

     In fact, the test I described did exactly as you suggested. In the .exe, it calls the beeping VI by name, not path. (Yes, it's a path constant, but the path constant contains only the name of the VI, not the path to where it is on disk.

     So again, the test indicates that the dynamically-called vi is loaded into RAM when the exe is first run. There is no way the .exe could access the VI on disk, yet it does beep.

     I haven't tried loading the parent class by name yet. Since the last posts on the big project, I have discovered other issues that are very likely contributing to the problem. The classes are all "mixed". There are composite classes which contain multiplie other classes as dependencies, and there are data sharing mechanisms that cuse all the classes to have all the other classes as dependencies. None of this is conducive to making plugins, for whichg you need the plug-in class to not hane any dependencies on other plug-in classes.  So we have a lot of work to do now to decouple things before proceding.

-------------------------------------------------------------
David Thomson Original Code Consulting
www.originalcode.com
National Instruments Alliance Program Member
Certified LabVIEW Architect
Certified Embedded Systems Developer
-------------------------------------------------------------
There are 10 kinds of people: those who understand binary, and those who don't.
0 Kudos
Message 20 of 34
(662 Views)