LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Dynamic dispatch and different return classes

Hi,

 

In my current project I have a HAL that handles different device types in a single library. The picture below contains the current HAL Classes. All the devices are children of the DSSP class.

HAL Contents.png

 

Since I need to load the HAL components I also created a plugin loader that can return the requested classes. However I would like to create a universal dialog where the user can select the requested instance of the HAL.

 

So I created a Plugin Loader Class and made the individual loaders into children of this class (see picture below). Now I'm hoping that I can use dynamic dispatch to select the correct plugin loader. (note: all the methods of the "Plugin Loader.lvcalss" are set to must override)

Plugin Loaders.png

 

However his generates a problem for me. Since the Plugin Loader->Load can only return the DSSP class and the actual loaders return their respective class I get a broken run button for all the other Load's.

Frontpanels Load.png

 

So I am hoping you can tell me what I miss here and how I can fix this.

 

Tim

0 Kudos
Message 1 of 16
(4,023 Views)

Tim,

 

how does your loader look like (in the code)?

I honestly don't understand why you require specific loaders at all. You use a general loader which simply reads the classes by "Get LV Class Default Value" by passing the value to the selected lvclass file.

Using a "To more specific class", you verify compatibility of the selected class to the parent (DSSP). THIS DOES NOT REMOVE THE INFORMATION ABOUT THE CHILD.

So essentially, you use the resulting class wire to call dynamic dispatch methods which are either defined by the parent or overriden in the inheritence path down to the specific child class.....

 

The only situation where you might want to use specific casts of the class wire is if you want to call methods unique to a specific child class......

 

Norbert

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
0 Kudos
Message 2 of 16
(4,020 Views)

Norbert,

 

Thanks for the quick reply. (in the current spam wave her on the board)

 

Well my code is below. It is the "Standard" try to load a class from the filesystem check if we can cast it to the required class, if yes add to array, if no, clear error and do nothing code to load classes from disc.:

DP Generator Loader.lvclass_Load.vi Block Diagram.png

 

However since I'm still (relative) new to GOOP (and OOP in general) I have some issues understanding your post.

 

The reason I needed different loaders is due to the constant class type (DP GEN). On the file system I have multiple classes that I need to load depending on the connected hardware (for now it are only dummy's but still...):

DSSP Classes.png

 

So this is why I (think at the moment) that I need multiple Loaders. This is due to the "Constants" as input and the output.

0 Kudos
Message 3 of 16
(4,003 Views)

Tim,

 

i think that you have to a certain degree (not completely!) a faulty design.

From what i understand from your second screenshot, you want to use a set of different generator devices. The point is, that each group of generators require different, specific functions.

So in order to proceed:

1. You have a general base class DSSP, which defines a basic sets of "must-have" functions for all instruments. DSSP can define functionality common to all instruments, but often, the specific instrument class uses dynamic dispatching to add/modify/define functionality unique to the instrument.

2. You insert a new class as child of DSSP for each type of generator (e.g. DP). This class adds new functions to DSSP specific to DP, but common to all types of DP generators.

3. You re-configure all DP generator classes to be children of the new class from 2.

4. Make sure that each type of generator gets a unique folder in order to remove "incompatibilities" during loading/initializing the actual instruments.

5. Regarding the set of functions you want to use in your application, you can

5.a) Generate a single loader, which returns any generator as "DSSP". You can only use the "must-have" functions mentioned in 1.

5.b) Generate a loader for each generator type. This does require, however, that you handle specific class wires in the caller. That is acceptable as the caller wants to use those functions unique to that specific type of generator.

 

Are you familiar with IVI (Interchangeable Virtual Instrument)? This is a good reference about abstraction of instruments using well defined classes of instruments.

 

Norbert

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
0 Kudos
Message 4 of 16
(3,994 Views)

Norbert,

 

I partially agree,

 

Point 1, 2 and 3 I have done (see below for the full DSSP list)

Full DSSP classes List.png

 

The actual DSSP modules and the DSSP class are both in a different projects.

4: I can do, but the casting trick also works

 

5: I would like to do 5B (and I think I'm doing now) since each caller only needs their respective class.

 

I tryed to start with IVI but failed fully, however if you have a solid starting point I'm interrested.

 

Tim

0 Kudos
Message 5 of 16
(3,987 Views)

Tim,

 

your screenshot shows your setup of the sources in an organizational view, but not as inheritance hierarchy. So i am not sure if it really helps.

What i understand from it is that each generator (DP, RH, ...) is directly inheriting from DSSP. So, option 5.b) does not make much sense, because it essentially erases the purpose of using LV-OOP in your application.

 

What still might make sense is to handle each instrument as DSSP and then adding proper dynamic dispatch methods. As the screenshot shows, you don't have any dynamic dispatch in the base class DSSP, only "Close" and "Init". Obviously, the child classes do not provide specific overrides......

 

Have you already seen this developer zone entry?

 

If looking for further information on IVI, you might want to visit ivifoundation. A rather good presentation on how to use IVI can be found here.

 

hope this helps,
Norbert


PS: IVI requires the instrument to officially support IVI. So it is something the vendor of the instrument has to develop and support....

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
0 Kudos
Message 6 of 16
(3,981 Views)

Hi Norbert,

 

I think we are not 100% on the same page (could be my error).

The picture from the previous post is the HAL itselve. Below in a screenshot of the implementation of a HAL device.

Implementation of actual HAL class.png

So I'm providing specific overwrites for each class.

 

I did see the developer zone entry, actually my entire HAL code is based on the HAL sample provided there.

 

About IVI: part of the hardware is developped internal and part is developed by external manufactures that never heard of IVI, so that won't be a option.

 

So now you know that my HAL should be fine (and it works OK) back to my original question. How can I get the correct data from the sub-vi's. A trick I could use is just to return the required path and convert it there to a class. Since the paths are allways in a constant format this looks the best option to me (at least for now).

0 Kudos
Message 7 of 16
(3,892 Views)

Hello Tim,

 

I just saw this post and I have a few quick questions to get a better grasp of your current situation:

- Can you share any example code?

- Can you share a Class Hierarchy (From inside the project select "View" and then LabVIEW Class Hierarchy)?

 

Thanks in advance!

Kind Regards,
Thierry C - CLA, CTA - Senior R&D Engineer (Former Support Engineer) - National Instruments
If someone helped you, let them know. Mark as solved and/or give a kudo. 😉
0 Kudos
Message 8 of 16
(3,831 Views)

Hello ThiCop,

 

As requested: Attached is the class Hierarchy.

LabVIEW Class Hierarchy.png

Before I took the screenshot I ran one of the loaders so all the childeren (that I need) are loaded into memory and show in the screenshot.

 

The other (semi-blurred) classes are from the actor framework and some (small) expiriments to get this working.

 

About the sample code: At the moment I don't have any since dynamic dispatch isn't working.

 

The idea behind this code is that I can load the configuration for the actors from a file but also show a dialog if there is no configuration and/or the user wants to change the configuration. (Or are there better ways to acomplish this?)

 

Tim

0 Kudos
Message 9 of 16
(3,824 Views)

Hello Tim,

 

I am not a 100% sure that you need a separate Plug-In Loader Class Hierarchy.
I think one Plug-In Loader class should perfectly suffice.


Wouldn't it be simpler to add an extra Dynamic Dispatching VI/method called something like ("get children") to all classes of your existing DSSP class hierarchy?

 

This way the DSSP version of get children would return REF, DPGEN, RHGEN, TEMP G and TEST R.

By using dynamic dispatching and a "tree"-like disk hierarchy (that matches the "tree" in your class hierarchy) you could quite easily create a "Plug-In loader".

 

By using this approach you can still have a Plug-In Loader Class, but this class would then just reuse the DSSP Class Hierarchy you have already defined.

 

PS: I know some people might "shoot" me for suggesting a tree-like class hierachy, but for a HAL it can be doable (as long as your class hierarchy is not very deep).

 

 

Kind Regards,
Thierry C - CLA, CTA - Senior R&D Engineer (Former Support Engineer) - National Instruments
If someone helped you, let them know. Mark as solved and/or give a kudo. 😉
0 Kudos
Message 10 of 16
(3,770 Views)