Jump to content

Namespacing objects in a build makes them "different"


Recommended Posts

I had a difficult time trying to decide which category to put this in - it's a tricky one, so here goes:

I've got a simple application: There's a "Caller" (a built application that the user opens) and a "Callee" VI on disk that the framework opens - nothing too difficult about that so far. The Caller has an object in it where I set some stuff, then I want to pass the object to the Callee through it's connector pane:

post-181-0-88857000-1341688052_thumb.gif

Then, when called, the Callee displays the stuff to the user:

post-181-0-97390500-1341688164.gif

When I run this in the development environment, it works fine. When I build it, it works fine too.

When I build the Caller application, if I include dependancies (read: subVIs) in the Caller and Callee that are the same (read: have the same name), calling the Callee from the built Caller won't work: it errors out with the Callee being "broken" (it's not really broken, there's just a namespace collision, so it refuses to load it). And I'm cool with that - the solution is to namespace the dependancies in the build, which is fine.

So "what's the problem?!?" I hear you ask!

All this worked great until I started trying to pass an object from the Caller to the Calle through the connector pane. (I think) Since the class is namespaced differently in the built Caller to the non-built Callee, I get

Error 1031 occurred at Open VI Reference in Caller.vi

Possible reason(s):

LabVIEW: VI Reference type does not match VI connector pane.

VI Path: C:\Users\christopher_relf\Desktop\Passing Objects between name-spaced application instances\Callee\Code\Callee.vi

...which, as you can imagine, sucks. I totally understand why it's happeneing, and even agree that this is the way it should be, but that doesn't help me complete my application.

I want to pass an object between a namespaced-exe Caller and a VI Callee - I don't want to deconvolute the object's data to an intermediary (like a variant or string I guess) and rebuild it to a copy of the object on the other side (unless I really have to - but I can't think of a generic way to do it that I like right now). Does anyone have any bright ideas? Hopefully I'm missing something easy, right? :)

I've included an example below.

//Crossposted to NI Discussion Forums.

Passing Objects between name-spaced application instances.zip

Link to comment

Sounds to me like this is the sort of thing source distributions were made for. If I recall you can still strip diagrams despite them being called "source" if that's a concern. Put whatever classes are used in the exposed APIs into the distribution and exclude the types from each of your application build specifications.

Packed libraries in theory would work too, but uhh, I'm personally not even close to trusting them given the headaches they've caused me the few times I tried using them.

Link to comment

Sounds to me like this is the sort of thing source distributions were made for. If I recall you can still strip diagrams despite them being called "source" if that's a concern. Put whatever classes are used in the exposed APIs into the distribution and exclude the types from each of your application build specifications.

Are you suggesting having a built Caller exe, a Callee vi, and a source distribution with all the shared stuff in the middle? That sounds horrible, and unmanagable.

Packed libraries in theory would work too...

In what way? (I"m actually distributing the Callee and its dependancies in a PPL, but that's beside the point in this scenario).

I'm personally not even close to trusting (PPLs) given the headaches they've caused me the few times I tried using them.

Can you expand on that? I've had a few issues, but mostly due to my own misunderstandings on how they work. Now that I've got a good working knowledge of them, I think they fill a good niche.

Link to comment

Hey crelf,

I'm short on time and I didn't even have time to open your example, thus, I hope I understood your question good enough.

I think I'm doing about the same thing and yet I don't have to play with any namespaces and it works just fine.

I guess the main difference between your implementation and mine is that the callee in my case inherits from a class contanied inside the caller, however, I'm not sure if this is the reason my case works and yours doesn't.

So, I'll try and describe what I did:

1. my caller is a version of the UI Framework https://decibel.ni.com/content/docs/DOC-15014

2. my callee is a LVLibP plugin that inherits from a generic class that is conained in the caller's project https://decibel.ni.com/content/docs/DOC-19176

3. I pass the status of some subject through a db class (created in the caller) through the connector pane of the callee which while it is being loaded in the callee http://lavag.org/topic/15712-best-way-to-share-data-from-different-subpanels/ see my post there

P.S. - this design is in progress and my boss told me this part of my design works in the deployed version. I didn't see it working with my own eyes until now since I'm busy with some other project at the moment.

We posted at the same minute and I didn't see mje's post :)

I too had some trouble with the LVLibP's at first but it truned out to be a driver problem and once set they work smooth. I love them!

Link to comment

Well I might not be interpreting your situation correctly. Unfortunately won't be able to look at your example for a while either. But it would seem to me you need some kind of third component. I'm interpreting the situation as you have two executables which you want to operate independent of one another, but want to be able to move (non-serialized, that is native LabVIEW) data between them? That to me implies some sort of common intermediary is needed which contains those types.

As for packed libraries, all I can say is twice I've tried to use them in a large project of mine, and twice I've had to revert because the IDE became simply unusable (slow and unstable). My thought was this third component could in theory be a PPL.

Link to comment
I'm interpreting the situation as you have two executables which you want to operate independent of one another...

Nope - one executable that calls a vi.

As for packed libraries, all I can say is twice I've tried to use them in a large project of mine, and twice I've had to revert because the IDE became simply unusable (slow and unstable).

That's really quite interesting - I've never had that issue. Have you got an example, or have you reported that to NI?

My thought was this third component could in theory be a PPL.

I guess it could, but I'd rather not have a third component at all, if possible. Maybe take a look at the code when you get a chance: that should make everything much more clear.

I'm short on time and I didn't even have time to open your example, thus, I hope I understood your question good enough.

I think I'm doing about the same thing and yet I don't have to play with any namespaces and it works just fine.

Thanks for the reply 0_o, but I don't think it quite applies in my situation. I'd apprecaite it if you could take a look at the code I uploaded if you get a few minutes - : that should make everything much more clear.

Link to comment

It took me a little while to understand that "namespaced" meant using the build option "Apply prefix to all contained items" in "Source File Settings" for dependencies in the build spec. Once I made that connection everything makes sense. This isn't really namespacing. This is changing the name of every dependency. So after the build Caller.vi references a class named "namespace.Shared Class.lvclass". Since Callee.vi didn't go through the build, it references the class "Shared Class.lvclass". A VI that has a single input of type "Shared Class.lvclass" is not going to match a strict VI reference with a single input of type "namespace.Shared Class.lvclass" so the open of the reference fails.

If you are going to rename the class during the build, then all plugins must be rebuilt against the renamed version. You can't really do that if the renamed version is only present inside the application. There are a few other options though.

  • You could include your plugins in the application build as "Always Included" files. This doesn't create much of a plugin framework, but in some cases that is acceptable.
  • You can make the application build put its dependencies outside the application. Create new destination for a sub directory, then change the dependencies to build to there. Then in your plugin projects (Callee's project) reference these files instead of the original "Shared Class" source. Then when Callee is loaded, it will agree on what all the dependencies are named. This is similar to the solution of creating the shared items as another build, but avoids actually having a separate build step.
  • You can build the shared items as a separate distribution and have both "Caller" and "Callee" projects reference that build output. This doesn't have to be built as a PPL. It could just be a source distribution, but either way it requires a separate project and build increasing maintenance.
  • You can not rename shared dependencies going into the application. For items that will be referenced from plugins, you can add them to the project directly (instead of having them just show up in dependencies) and not have them be prefixed. This also will make it clear which items are valid to be referenced from plugins. That makes it clear to you which items might break plugins if you modify them and easier to tell others writing plugins what things they can reference versus items they should not reference.
  • Many other variations of these themes.

To decide which approach to take, I'd want to know what you are really trying to get out of using a plugin approach. Who is going to be building the plugins? Are the plugins supposed to be able to update independently of the application? Should the application be able to update without invalidating the plugins? What VIs/classes used in the application should be able to be referenced from the plugins? What were you trying to accomplish with the name prefixing option?

  • Like 2
Link to comment

That doesn't come as a complete surprise and it is a bit off topic.

Lets say you were using a driver which is 32bit but you also have another version which is 64bit or for a different platform.

You would have to build a different distribution for each of those cases no matter what tool you are using.

LVLibP is actually an advantage here since all you need is to rebuild all the LVLibPs according to the hierarchy and your application will run on your device.

A simple script can do it and an automatic builder is the place to put it in.

BTW, if someone needs me to convert the code to LV8.2 please ask.

Link to comment

I would avoid packed libraries if you can. They do not seem to be multi-platform (not even on the same OS).

This is what happens if I try and load your library in LabVIEW 2011 x64 (it loads fine in x32).

That is because they are pre-compiled therefore you will only be able to use them on the same processor architecture and OS. Assuming you end up with a built executable this will not matter as you will run on the same runtime engine.

Link to comment

That doesn't come as a complete surprise and it is a bit off topic.

Lets say you were using a driver which is 32bit but you also have another version which is 64bit or for a different platform.

You would have to build a different distribution for each of those cases no matter what tool you are using.

LVLibP is actually an advantage here since all you need is to rebuild all the LVLibPs according to the hierarchy and your application will run on your device.

A simple script can do it and an automatic builder is the place to put it in.

BTW, if someone needs me to convert the code to LV8.2 please ask.

Well. It's not off-topic since it is about code that you posted as an example in this topic

.

If you are happy to limit the portability of your source distributions, That's entirely up to you (I prefer the input from as many people as possible). One of the beauty's of LabVIEW is that it is multi-platform so anyone with LabVIEW x32/x64 or even linux and a Mac can use source posted on the forum. Only those with windows AND LabVIEW x32 can load your source.

That is because they are pre-compiled therefore you will only be able to use them on the same processor architecture and OS. Assuming you end up with a built executable this will not matter as you will run on the same runtime engine.

What is that saying about "assumptions being the mother of all muck-ups"? This is the very reason that I avoid packed lvlibs at all costs. I see no up-side but one huge down-side.

Link to comment

I see no up-side but one huge down-side.

That is a downside but an executable is also no good for sharing code on a forum, that's just not what they are for. The trade off that you are making is that the code is precompiled making it much quicker to load, build and having all the compiler optimizations active. The single file makes them easy for distributing plug ins for plugin architectures as well.

Link to comment

My inclination is to follow the plugin example over on the Dark Side using packed libraries. I have had some trouble with using packed libraries with an error message about including compiled code when trying to create the child objects. I was able to get around this by compiling the parent with the debug flag turned on. There is a fair amount of housekeeping that has to be done to make this structure work, but it's easy to create a new plugin once you've got the setup down.

The portability between 32 and 64 bit Windows concerns me. I'm wondering if there is a problem when an executable that uses plugins that are both built in 32-bit are run on 64-bit. I see an executable loading packed libraries as the use case rather than a VI in the development environment.

Link to comment

What is that saying about "assumptions being the mother of all muck-ups"? This is the very reason that I avoid packed lvlibs at all costs. I see no up-side but one huge down-side.

If you consider PPLs as a baby step toward a built EXE, then you can approach them with the right mindset: valuable in certain use cases, but completely useless in others.

  • Like 1
Link to comment
It took me a little while to understand that "namespaced" meant using the build option "Apply prefix to all contained items" in "Source File Settings" for dependencies in the build spec. Once I made that connection everything makes sense. This isn't really namespacing. This is changing the name of every dependency.

You're absolutely right - I should have called it "Namechanged" instead of "Namespaced", or the like.

So after the build Caller.vi references a class named "namespace.Shared Class.lvclass". Since Callee.vi didn't go through the build, it references the class "Shared Class.lvclass". A VI that has a single input of type "Shared Class.lvclass" is not going to match a strict VI reference with a single input of type "namespace.Shared Class.lvclass" so the open of the reference fails. If you are going to rename the class during the build, then all plugins must be rebuilt against the renamed version... There are a few other options though...

Maybe I'm misunderstanding the options you list, but I don't see a solution there. The issue is two fold: I can't load a plugin that has a dependancy that has the same name as one of the application's dependancy (the plugin is reported as broken) - that's why I have to namechange one of them. Your solutions seem to have the dependancies in a shared resource outside the Caller and Callee - won't this have the same issue?

To decide which approach to take, I'd want to know what you are really trying to get out of using a plugin approach. Who is going to be building the plugins?

Anyone on my team.

Are the plugins supposed to be able to update independently of the application?

Yes.

Should the application be able to update without invalidating the plugins?

Yes.

What VIs/classes used in the application should be able to be referenced from the plugins?

I don't understnad this question - are you asking for a list of them?

What were you trying to accomplish with the name prefixing option?

Being able to load the Caller dynamically from the Caller application.

Link to comment

Maybe I'm misunderstanding the options you list, but I don't see a solution there. The issue is two fold: I can't load a plugin that has a dependancy that has the same name as one of the application's dependancy (the plugin is reported as broken) - that's why I have to namechange one of them. Your solutions seem to have the dependancies in a shared resource outside the Caller and Callee - won't this have the same issue?

You can't load a plugin that has a dependency that has the same name as one of the application's dependencies if the dependency is supposed to be different. In your case the dependency is a class that is passed from Caller.vi to Callee.vi so in fact it is critical that both sides do link to the same instance. This is the only way it will work. Whether that shared class is inside the EXE or not is a separate issue. It can be acceptable for this dependency to be inside the EXE and the dynamically loaded VI will work just fine. Your original project had 2 application builds: Caller and Namespaced Caller. Caller.exe works just fine for me (as long as I make sure Callee.vi is saved in the same version before running Caller.exe).

The point of this exercise is not to avoid sharing but to figure out how to properly share. The suggestions I gave were all different ways of sharing those dependencies. They all have tradeoffs between robustness and development overhead. Take your pick. The real key is to make sure you understand which items are being shared. Any change to a shared item could cause you to have to rebuild both sides.

Link to comment
You can't load a plugin that has a dependency that has the same name as one of the application's dependencies if the dependency is supposed to be different.

The dependancy isn't *supposed* to be different - but it might be.

Is this statement true?

You can't load a plugin that has a dependency that has the same name as one of the application's dependencies.

If so, you've answered my question.

Your original project had 2 application builds: Caller and Namespaced Caller. Caller.exe works just fine for me (as long as I make sure Callee.vi is saved in the same version before running Caller.exe).

What do you mean by "saved in the same version"?

The point of this exercise is not to avoid sharing but to figure out how to properly share. The real key is to make sure you understand which items are being shared. Any change to a shared item could cause you to have to rebuild both sides.

So you've got to my reall issue here: the point of the exercise is *not* not to avoid sharing - it's to allow my developers to create their own plugins using VIs from any of our internal reuse libraries without having to worry about if I used any of the same reuse VIs in the Caller (I *almost* achevied this by renaming in my caller).

I *think* you're telling me that what I want to do can't be done - but I;m not completely sure.

Link to comment

So you've got to my reall issue here: the point of the exercise is *not* not to avoid sharing - it's to allow my developers to create their own plugins using VIs from any of our internal reuse libraries without having to worry about if I used any of the same reuse VIs in the Caller (I *almost* achevied this by renaming in my caller).

I'm assuming your internal reuse libraries are inside the user.lib and would thus show up in the dependencies. You can, in a build specification for the packed library for a parent class, apply a prefix to anything in the dependencies. That should allow your developers the freedom you're looking for so long as no one picks the same prefix for the same original subVI.

Link to comment
I'm assuming your internal reuse libraries are inside the user.lib and would thus show up in the dependencies.

Yes, that's right.

You can, in a build specification for the packed library for a parent class, apply a prefix to anything in the dependencies. That should allow your developers the freedom you're looking for so long as no one picks the same prefix for the same original subVI.

Unless I'm missing something with your explanation (which is entirely probable), there's a couple of issues with what you're saying: there's no parent/child heirachy here - in fact, the issue isn't anything to do with LVOOP at all - it's to do with any dependancies with the same name. The more important issue is that I already tried what you're talking about, and it doesn't work: dependancies with the same name cause the Caller to see the Callee as broken.

Link to comment

So you've got to my real issue here: the point of the exercise is *not* not to avoid sharing - it's to allow my developers to create their own plugins using VIs from any of our internal reuse libraries without having to worry about if I used any of the same reuse VIs in the Caller (I *almost* achevied this by renaming in my caller).

I *think* you're telling me that what I want to do can't be done - but I;m not completely sure.

But you defined your plugin interface in terms of an lvclass. You can't have a class in your interface unless both side are going to agree on the class definition. If you really want both side to not share any dependencies, then you can't have any dependencies in the interface between the sides. If your strict VI reference uses any class or typedef, then that definition must be shared. To operate the way you wanted, you can only use core data types in the connector pane of your plugins.

If you have more than one plugin, then you need to make sure each plugin is built with a wrapping library or name prefixing to keep them from conflicting with each other. At that point whether the top level app does this or not is unimportant.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.