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 Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
0 Kudos
Sam_Sharp

Allow type-casting between classes types in PPLs / .lvlibp's (or some other solution that works)

Status: Declined

Any idea that has not received any kudos within a year after posting will be automatically declined.

I have used Packed Project Libraries (PPLs) in a couple of smaller projects before with mixed amounts of success. Now I have read all of the caveats/pitfalls and I have a pretty good understanding of how they work (same application instance but under a different namespace) but my main problem still comes down to this: Passing class references into PPLs just breaks and causes me severe headaches.

 

Here is the situation...I pass everything I need into my plugin VI as a variant because within the PPL, you can do 'variant to data' and even if it is a type definition it will collect the correct reference which is valid in my application. This doesn't work for classes - the variant to data node complains because the data type does not match:

2015-05-18_13-05-47.png

Error out 2 throws error 91 whilst the others are fine - even the user event which is based on a type definition in a library - QMH.lvlib:ctl_Msg.ctl.

 

The reason for this is that the variant passed in Class.lvclass and the data type it's trying to convert it to is Plugin.lvlibp:Class.lvclass. Apples != Oranges. The problem is that it IS the same class so I don't see why I should get an error here (because QMH.lvlib:ctl_Msg.ctl also becomes Plugin.lvlibp:QMH.lvlib:ctl_Msg.ctl, right?). If the type/class version/mutation in the PPL is incompatible with the main application instance then throw an error but if it's just because the namespace is different I want to be able to use that class in my PPL.

 

Can I please tell LabVIEW somehow that Plugin.lvlibp:Class.lvclass is actually Class.lvclass (including any classes used inside) so that I can use it inside my PPL with the same data space.

 

This sort of transfer mechanism between namespaces is already sort of possible with the 'Get Exported File Path' VI, so can I have a psuedo-equivalent for classes please?

 

I know I can build Class.lvclass and all of it's dependent classes into a 'shared' PPL but that would mean shipping my re-use library as a PPL and all sorts of other reasons (like not shipping vi.lib as PPLs).

 

I'm not actually sure what the solution would look like - there are far more intelligent people than me on here who can put forward some ideas of how to implement the idea - all I know is that I want to be able to pass my class into the PPL and have it work.


LabVIEW Champion, CLA, CLED, CTD
(blog)
9 Comments
AristosQueue (NI)
NI Employee (retired)

> Can I please tell LabVIEW somehow that Plugin.lvlibp:Class.lvclass

> is actually Class.lvclass (including any classes used inside) so that

> I can use it inside my PPL with the same data space.

 

No, no one can. They are different classes. I tried various shoehorns in the code base, and only created a lot of ambiguous situations. For example, even if all the data types are the same, the method implmentations or the default value of the class or even its inheritance might be different -- if not in the immediate level, then in some higher level.

 

You have built a class as a PPL. Why aren't you able to use that class in all the places that are generating your data? Mixing the packed and unpacked versions is not a good idea at all.

 

There is a hack -- if you flatten to XML and then modify all the ".lvlib" instances to be ".lvlibp" (or vice versa) you should be able to unflatten as the other class. That's the best I can offer to you.

Sam_Sharp
Trusted Enthusiast

To expand on my particular problem: I have a re-use library which acts as a data repository for a core application framework. It's class-based and essentially the top-level class private data is a DVR variant lookup table. The variant attributes are data handler classes which contain meta-data about the signal and the signal data itself (also a class).

 

So I have: DataServer.lvclass - the top level API, DataHandler.lvclass (data type of my variant attributes) and DataCore.lvclass and a number of child classes of DataCore.lvclass for different data types (the idea being that it's extensible by the user to add other supported data types).

 

These classes are not built into PPLs - they are distributed as classes as part of a VI Package installed into vi.lib. Other components (e.g. logging, display) depend on these classes.

 

I want to be able to write plugin modules to my core framework which I can distribute as PPLs which can use the same library to access the repository (e.g. to add support for additional hardware, add additional UI display panels). Obviously by doing that, the classes get pulled into the PPL as part of the dependencies of the class.

 

Ok, so the workarounds that I've considered for my application are:

- Distributing the data repository library as a PPL and updating the entire framework to use the PPL versions (as you had assumed I had done). As far as I understand it, this would cripple the extensibility of the framework (to add support for additional data types) and would mean including a (not necessarily that) bloated PPL (as it would include child data classes not used by the application). It would also prevent debugging/probing of the data repository components and create an additional step in producing the distributable package (to build the PPL before building the package). I believe you commented on a suggestion to ship vi.lib as PPLs and dismissed it for the same reasons I'm reluctant to distribute my re-use libraries as PPLs.

- Create a 'plugin API'/server and have any data going to/from the plugin sent to/from the main application through that interface (using queue/event references and native data types).

 

Option 1 is probably the 'correct' solution given the current limitations but I can't help but feel that I'm being artificially hindered by something that should work. We'll probably end up going down the route of Option 2 and create a clearly defined interface to avoid getting stung by this again. I'm open to other ideas/suggestions on which one would be more appropriate though!

 

The simplest example I can think of is that if I flatten something to a string and send it over the network - as long as it's compatible at the other end I should be able to unflatten it. If it's not compatible then fine - throw an error. I can understand that 'compatible' can be ambiguous which is why it is more difficult with classes than with type definitions etc.

 

To comment on your 'hack' - I have been able to rebuild the DataServer.lvclass successfully inside the PPL by creating class methods to 'convert class references to variant' and 'convert variant to class' and also discovered a similar 'hack' by doing a string replace after flattening the class to string but of course that only works for the DataServer.lvclass - when I try to do anything with the data itself (DataHandler.lvclass) - they all fail.


LabVIEW Champion, CLA, CLED, CTD
(blog)
AristosQueue (NI)
NI Employee (retired)

> I want to be able to write plugin modules to my core framework which I can distribute as PPLs which

> can use the same library to access the repository (e.g. to add support for additional hardware, add

> additional UI display panels). Obviously by doing that, the classes get pulled into the PPL as part of

> the dependencies of the class.

 

You should be writing the plug-ins using the PPL version of the class, not the source version of the class. Building a PPL does not pull in dependent PPLs.

 

You have Framework.lvlib:Parent.lvclass... build that as a PPL.

Then write Plugin.lvlib:Child.lvclass in a new project using Framework.lvlibp (I emphasized the "p" just because it is easy to miss).

Build Plugin.lvlib into a PPL.

 

Now both are distributable.

AristosQueue (NI)
NI Employee (retired)

> I believe you commented on a suggestion to ship vi.lib as PPLs and dismissed it for the

> same reasons I'm reluctant to distribute my re-use libraries as PPLs.

> - Create a 'plugin API'/server and have any d

 

For vi.lib, there are different rules because of the platform independence issue and because not everyone wants componentization -- they want to end up with a single EXE, not multiple files they have to track. I have considered shipping a project inside vi.lib that would include the build spec needed to generate the PPL.

 

For an actual plug-in system that is being distributed out to users and needs independent revision, there's no question I would use PPLs. No question whatsoever.

Sam_Sharp
Trusted Enthusiast

I don't think I've made myself clear - I want to distribute my plugin as a PPL, I don't want to distribute my data repository library (which myself and other developers on my team use) to other developers as a PPL (so that both the EXE and plugin PPL refer to the same namespace). I want to use my data repository library in my application and plugin source code but I can't because the namespaces of the classes in the executable and PPL are different.


LabVIEW Champion, CLA, CLED, CTD
(blog)
AristosQueue (NI)
NI Employee (retired)

Not going to be possible in any sane way.

 

Why do you want this? Why do you not want your EXE to use the PPL? I don't know of any reason to oppose that, and it is the thing that makes what you are wanting to do work... and work really well.

Sam_Sharp
Trusted Enthusiast

Ok, so here's why I want it to be able to work:

 

I have a simple messaging library based on queues/events of a string/variant type definition. This library is a .lvlib distributed as a VI Package. I can use that library without modification in both my EXE and PPL and I can pass the reference into the PPL by converting it to a variant and then converting back within the PPL (even though the namespace is different). OK, I can't 'obtain queue' within the PPL because it will complain the type is different but I can at least wire it into the PPL as a variant and use it.

 

I want to be able to do the same with my class-based data repository library. I want to be able to pass the class reference into the PPL and use it like I can with my messaging library.

 

I don't want want to have to distribute my data repository library as a PPL as 95% of the time it's only used within a single application without plugins. If I don't distribute it as a PPL and just build it into a PPL in the projects I need it then I have some projects where the PPL is used and some where the uncompiled classes are used - this makes it very prone to make errors (by accidentally using the wrong version in the software). I also have other components distributed as VI packages - these also depend on the data repository library - do I make them depend on the PPL version or the non-PPL version? I also don't distribute my data repository library as an lvlib...it's just a series of classes...if I put them in an lvlib/lvlibp then the whole lot will be included in the PPL. If i then extended one of the data type classes, I would then end up in the same situation again!

 

Just out of curiosity, would it be possible to create actors in the actor framework, build them into a PPL, load them into an executable and have them send/receive messages to modules in the executable? I think that's a similar scenario/use case and it doesn't work there for the same reason it doesn't work in my application.


LabVIEW Champion, CLA, CLED, CTD
(blog)
AristosQueue (NI)
NI Employee (retired)

> in the projects I need it then I have some projects where the PPL is used and some where the

> uncompiled classes are used - this makes it very prone to make errors (by accidentally using

> the wrong version in the software).

 

I agree, which is why I would use it as a PPL always everywhere.

 

> do I make them depend on the PPL version or the non-PPL version? 

 

The PPL version. Always.

 

> If i then extended one of the data type classes, I would then end up in the same situation again!

 

No. You build the core as a PPL. The callers can be shipped however you want -- as their own PPL or as an EXE or DLL or loose files. If you do build the callers as a PPL, they do not pull in the dependent PPL. The build references external PPLs.

 

That's the only pattern that is going to work for you. There won't be any improvement in this situation from National Instruments, I'm afraid. The namespace is different and even if we repaired the namespace issue, then you'd have the problem of trying to load two things of the same name in to memory at the same time in the same context. It ain't going to work no matter how we slice it. You need to be using the same class in all parts of your app. The exact same class. Anything else is just going to be an uphill stressful fight that probably won't work in the end for some obscure reason.

Darren
Proven Zealot
Status changed to: Declined

Any idea that has not received any kudos within a year after posting will be automatically declined.