LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Type safe dynamic storage of inherited objects?

Solved!
Go to solution

In the meanwhile I found a "solution" - or at least something that works, but I don't really like it.

 

I had to move the device manager into base class (as suggested), but additionally override the manager implementation for each inherited class, so that each manager hold a collection of the same type.

That leads to the next problem: Finding out which manager holds which DeviceId. This is done by an additional Device Registry.vi (functional global, located in base class but actually independent), which does the DeviceId => Type mapping.

In summary a big effort just to manage some objects by ID (think of actions "delete", "clear" etc.)

 

If somone knows a more elegant way, please let me know...

 

Regards,

Alex

0 Kudos
Message 11 of 19
(720 Views)

Alex,

 

sorry, my fault. I miswired the output terminal of the class output of the manager.

Attached, you find an updated version of the example which works fine on my machine. Good news: The dynamic dispatch output is not necessary, so the device manager can be stand alone again!

 

All in all, Shane is correct that a simple "Preserve Run-Time Class" is sufficient....

 

Norbert

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
Message 12 of 19
(703 Views)

@Norbert_B wrote:

All in all, Shane is correct that a simple "Preserve Run-Time Class" is sufficient....

 


HeartSmiley Happy

Message 13 of 19
(699 Views)
Solution
Accepted by alex_bauer

alex_bauer wrote, in the initial post:

 

Storing and reading to and from manager works, at least until the VI borders are reached. Within the VI, the correct original type (e.g. "Device GPIB") is returned. Outside of the VI, the type is casted to "Device Base" and the wrong dynamic dispatched member VI gets called (Base implementation)

 

How can I safely dynamically store and read mixed objects of the same base class without loosing the concrete type?!


Your initial "Device Manager" has a bug in it: the "Device Object" output is mistakenly connected directly to the input rather than the the output tunnel of your Error case structure.  Thus, the output is always the same object as input, and is never the object stored in the Device Manager.  Connect the output properly and it works.  

 

FYI, objects never "degrade" or otherwise change classes.  Nor does use of dynamic dyspatch methods require the explicit identification of the child objects (that being the whole point of DD).  If they seem to, it's because of a bug or some misunderstanding somewhere.

Message 14 of 19
(687 Views)

Hello drdjpowell!

I can't believe it, your're right! Had to look twice to find the bug, thanks a lot!

More than that, it seems that I not even have to provide the correct class at the input now, after changing the device manager back from a base class member to a normal functional global without DD!

I will verify this tomorrow in the real application.

Seems I have to apologize for anything I might have said or thought about LVOOP in the meanwhile 😉 ...

Such a dumb mistake, I would have worked right from the start as intended.

 

Thanks again and best regards,

Alex

0 Kudos
Message 15 of 19
(678 Views)

Alex,

 

ok, this is what i attached (except you indeed even don't need the Preserve Run-Time Class).... 😉

Well, i just reviewed your initial approach and the only difference now is that the objects are stored in an array in the device manager rather than as variant attributes.

When working with variant attributes, these are themselfes variants again. So your object are cast to variant and back again.

 

Obviously, when an object is in a variant, you have to exactly specify the class of the object to get the correct object type back again (variant to data). That seems to be your original issue overall.

 

This was new to me as well, therefore all the confusion inbetween....

 

Norbert

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

Hello Norbert,

 

no, the original issue was just the wrong wiring. Now everything works as expected and I don't even have to wire the input for the "get" case. The device manager is now part of the application (where it should be). The terminals are defined as static base class objects (allows to call only "interface" methods, which are dynamically dispatched) but internally keep their class specific attributes => everything perfect now.

 

Regarding the device manager: there is no explicit casting required and the objects are handled correctly when storing them as variant attributes. The advantage of this approach is the faster lookup and built in key-value mapping and management. It also behaves differently, because I have to override the object in the "set" case to update an object instead of adding it to the array, even if it already exists.

 

Again, thanks for all your help and I'm glad it works now.

 

Regards,

Alex

0 Kudos
Message 17 of 19
(650 Views)

Alex,

 

ah, i see...sorry, i thought the miswiring was my fault 🙂

Correct, the miswiring in the device manager is already in the initial attachement of yours in place, which is, as far as i can see, the main reason for this thread at all.

 

One side note:

VI Analyzer could have helped in this issue (d'oh, haven't used it on my own!) as it would have critized the wire behind objects (the case structure)!

 

Short summary:

Provide code only if you tested it before using VI Analyzer. Also a ToDo on my side.....

 

Norbert

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
0 Kudos
Message 18 of 19
(646 Views)

For those new to LVOOP, it is helpful to keep straight the differences between the following pairs:

 

The class of a wire versus the object on the wire.

"Edit time" vesus "run time".

A Class versus an Object (an instance of a class).

 

These are all closely related.  Wires have a class type defined at edit time.  Objects exist at run time and can be of a child class of the wire they travel on.   The wires that an object travels on can change, but the objects class type never changes.

 

"Variant to Data" is about wiretype/edit-time (as are several other "change-wire" operations); "Preserve Run Time Class" is about objects/run-time (hence the name).

 

-- James

 

 

0 Kudos
Message 19 of 19
(639 Views)