LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Get LV Class Parent Name

@wiebe quoted exactly the sentences describing the issue. I don't know if I can explain it better than that. So we have a test sequencer that is built with LabVIEW and built into an executable. I want to be able to call from this executable any public methods from a LabVIEW build class just like TestStand is able to do. The class is not part of the executable, it can be any class compiled with the same LabVIEW version. I cannot make any modifications to the class being called.

Start asynchronous call cannot be used because we cannot know the method type (conn pane) so I am using Run VI method. Problem is that if a dynamic dispatch method is called and the loaded class is a child class, still the parent will be executed because when the user created that sequence step, he specified the path to the method from the parent (which is the expected way to do it). Also, if the method is not implemented in the child class, I need to know who the parent is so I can search for that method in the parent and call it from there. That's why I started this thread. As I mentioned in post #3, the solution that I found was to call 'Get Implementing VI Path' method from App -> LabVIEW Class. It does not return the parent name but gives you directly the path to the method that you want to call. If it's not implemented for the selected class, it will search for it in the ancestor classes.

Lucian
CLA
0 Kudos
Message 21 of 33
(1,147 Views)

For what it's worth, here's how I'm doing things:

Each step in a sequence is an object.  It references 0 or more code modules to be called.  It also optionally references a typedef for an Aux Data input to the code module, and the step also has a variant that contains the value for that custom data.  My step-settings dialog presents that step-specific custom data typedef in a sub-panel, and keeps it synced to the value in the variant.  The template for code modules looks like this:
st.png

 

All code modules must have the same connector pane.  In each code module, the "Aux Data" control is replaced by the custom typedef for the step (the step settings dialog keeps it synced with the step settings in the sequence).  The code that invokes a step, copies the custom data from the sequence step to the "Aux Data" control in the code module before calling the it (the code module is called by reference so the executive won't abort if the code module aborts).

The Step IO class has a set of properties that are available to all steps:
sio.png

So far, my hierarchy of step classes looks like this:
sth.png

"If you weren't supposed to push it, it wouldn't be a button."
0 Kudos
Message 22 of 33
(1,127 Views)

@drjdpowell wrote:

wiebe@CARYA wrote:

@drjdpowell wrote:

But other than just run it, what are you going to do with the reference?  Otherwise, this just appears to be an overly complicated way to dynamically call a DD method.  The simple, straightforward way of using a subVI seems much better, except for it not providing you with a reference.


The dynamic VI Server call allows you to start the VIs and continue without waiting for them to finish..

 


I didn't ask that.  A dynamic VI Server call on a DD method is easily done with a simple subVI.  Dynamically call the subVI and the subVI calls the DD method.  That is simple.  Why are you doing apparently much more complicated VI Server gymnastics to do the same thing?


Once you have a VI that does this in your toolbox, it isn't much work to use it.

 

I agree that making a VI and calling that dynamically is simpler. But if you have to do this a lot, at some point using VI that avoids the need for it starts to make sense.

 

Also, there are situations where you only get a name to call. The connector pane might not be known (only control names).

0 Kudos
Message 23 of 33
(1,114 Views)

@LucianM wrote:

In the meantime I found a solution by calling 'Get Implementing VI Path' method from App -> LabVIEW Class. For some reason this seems not to work every time but could be something wrong in my code, I didn't have time to investigate in detail.


I don't recall if I tried that one, or that there was a problem with it.

 

It's just very unpractical that you have to give the scope as an input. In the scope of the class, who cares if the method is public, community or protected? 

 

EDIT: It seems you can get the scope of the VI:

Get VI Scope.png

Of course that's useless if you only have a string... I usually use a static VI ref to the parent's method to call, so I can use it.

 

I do still have the need to climb up the hierarchy, because I want to get the class data (for serialization). Since none of the serialization functions return data if the class is default, I need to get it from the class's private data. So I need the class references of all ancestors.

0 Kudos
Message 24 of 33
(1,110 Views)

@LucianM wrote:

So we have a test sequencer that is built with LabVIEW and built into an executable. I want to be able to call from this executable any public methods from a LabVIEW build class just like TestStand is able to do. The class is not part of the executable, it can be any class compiled with the same LabVIEW version. I cannot make any modifications to the class being called.

Start asynchronous call cannot be used because we cannot know the method type (conn pane) so I am using Run VI method. Problem is that if a dynamic dispatch method is called and the loaded class is a child class, still the parent will be executed because when the user created that sequence step, he specified the path to the method from the parent (which is the expected way to do it). Also, if the method is not implemented in the child class, I need to know who the parent is so I can search for that method in the parent and call it from there. That's why I started this thread. 


Ah.  You're trying to build an "Arbitrary LabVIEW VI Sequencer" which you can use as a "Test Sequencer", rather than just building a Test Sequencer.

A hopefully amusing parable:

 

You are traveling to the town of Test Sequencer, and find yourself on a path in the Mountains of VI Server, contemplating the Rope Bridge of Library References.   A fellow traveller, familiar with these mountains, stops to discuss with you the issues of this rather rickety rope bridge.  A nearby stranger overhears this conversation and asks a question: 

"Why are you on this path?"

You explain, again, that you are travelling to Test Sequencer, but the stranger again asks:

"But why are you on this path?"

The stranger asks this because he's been to Test Sequencer, and he took a path through the Valleys of Abstraction Layers, a somewhat confusing route admittedly, but one with paved roads and stone bridges.

You then explain that you are going to Test Sequencer via the Volcano of Arbitrary VI Sequencer.  To which the stranger replies, "Yikes! That's a hard road!" then disappears down the mountain yelling, "Beware of the Monster of Root Loop!"

Message 25 of 33
(1,095 Views)

@drjdpowell wrote:


Ah.  You're trying to build an "Arbitrary LabVIEW VI Sequencer" which you can use as a "Test Sequencer", rather than just building a Test Sequencer.

It's not an arbitrary LabVIEW VI sequencer, it is a test sequencer that can control most instrument types that we use (using HAL), IVI instruments, create measurement files, reports, sequence variables, loops, conditions etc. I want to add the option to call any simple VI or class method VI for more flexibility.

I don't think Root Loop is going to be an issue. For the moment you cannot run multiple sequences in parallel (and not needed) and there is no UI updates to be done while the step with the VI call is executing.

So the more experienced traveler would simply not add this feature?

Lucian
CLA
0 Kudos
Message 26 of 33
(1,092 Views)

@LucianM wrote:

@drjdpowell wrote:


Ah.  You're trying to build an "Arbitrary LabVIEW VI Sequencer" which you can use as a "Test Sequencer", rather than just building a Test Sequencer.

It's not an arbitrary LabVIEW VI sequencer, it is a test sequencer that can control most instrument types that we use (using HAL), IVI instruments, create measurement files, reports, sequence variables, loops, conditions etc. I want to add the option to call any simple VI or class method VI for more flexibility.

I don't think Root Loop is going to be an issue. For the moment you cannot run multiple sequences in parallel (and not needed) and there is no UI updates to be done while the step with the VI call is executing.

So the more experienced traveler would simply not add this feature?


Sadly, the root loop also block when the user pulls down a VI menu...

 

I think the Run method doesn't wait for the root loop, but call by reference does. So I think you should be good.

0 Kudos
Message 27 of 33
(1,082 Views)

@LucianM wrote:

@Kyle97330 wrote:

I actually think you're solving this the wrong way.  It should never be "your job" to find out which VI in a class tree to call... that's the entire point of dynamic dispatch.


 It's not my job when I'm calling that method in LabVIEW but in this case, I'm calling that method from a LabVIEW executable and I am not the developer of the class being loaded so I cannot and don't want to modify it in any way. I just want to be able to call its methods. If the method requested does not exist in the class that is actually loaded, it's my job to find out what parent class has that method implemented and call it.


I'm 102.7% sure I'm not interpreting this correctly, but why not create a class to inherit from the 3rd-party class you don't want to modify and just call the method on that? You can create all overridable DD VIs, and just throw in a "Call Parent Method" on the BD. Now you don't have to worry about which parent implements it, LV will take care of it for you.....

0 Kudos
Message 28 of 33
(1,074 Views)

wiebe@CARYA wrote:


Sadly, the root loop also block when the user pulls down a VI menu...

 

I think the Run method doesn't wait for the root loop, but call by reference does. So I think you should be good.


Unless they have changed things in recent versions, "Run" method requires Root Loop and Async Call By Reference (ACBR) does not (but opening a reference capable of ACBR requires Root Loop).   Frameworks like the Actor Framework get around Root Loop by caching a pre-prepared reference to a pool-of-clones, so the Root-Loop blockable step only happens on startup. 

 

Whether Root Loop is a problem depends on application: UI stuff, generally not at all, safety features, critical.

Message 29 of 33
(1,067 Views)

@drjdpowell wrote:

wiebe@CARYA wrote:


Sadly, the root loop also block when the user pulls down a VI menu...

 

I think the Run method doesn't wait for the root loop, but call by reference does. So I think you should be good.


Unless they have changed things in recent versions, "Run" method requires Root Loop and Async Call By Reference (ACBR) does not (but opening a reference capable of ACBR requires Root Loop).   Frameworks like the Actor Framework get around Root Loop by caching a pre-prepared reference to a pool-of-clones, so the Root-Loop blockable step only happens on startup. 

 

Whether Root Loop is a problem depends on application: UI stuff, generally not at all, safety features, critical.


Ah, yes. I got it reversed.

 

Indeed, Run method uses root loop, Call By Reference doesn't.

 

Definitely a concern if you're planning on calling the Run Method in a loop. Menus (VI or control) will pause the sequence.. 

 

I to 'spawn' modules at start, so it doesn't bite me. Pretty sure that's intuition from being bitten in the past.

 

See Run Method should not run in the user interface thread - NI Community.

 

Also, One\Two Button Dialogs block the root loop: Change one and two button dialog windows do they do not block the root loop - NI Community

0 Kudos
Message 30 of 33
(1,063 Views)