Jump to content

Why do friends have paths?


Recommended Posts

The title sounds philosophical, and the question is kinda philosophical...

When you declare a library as a friend you need to provide a path to that library. I was expecting this path was only used to get the name of the library, however the LVLIB file (and I assume LVCLASS as well) stores the path and the name.

I thougth this was a bit strange. Here's why I would like to refer to friends by name and not by path:

I am writing an API, and an extended API (an add-on module), for convenience I would like to open up some functions that are private to API to the add-on. So I declare these functions as 'Community scope' and declare my add-on module as a friend. Everything works fine... In development.

Now I make a build of my API which installs the API into user.lib (hey and maybe sets a password on the library).

Then I start developing on my add-on module, which is broken since it cannot get to the private methods of the API, what happens is that LabVIEW is issuing a Cross-link warning dialog. Stating that it expects the add-on module on a different relative path to the API then it actually is. If I resolve this the API lvlib file will be changed. What if I update my API and replace it with a new version, then I have to re-connect (and alter) the API again. (I am not even talking about moving the add-on into user.lib)

This wouldn't have happened when I was allowed to define friends by name (here comes a very weak analogy to real life: 'I don't care about the cell-phone number of my friends, just about there names').

I can understand how changing the linking to 'by name' may compromise the validity of classes (a friend might alter data), however a friend of a lvlib cannot alter data (I rule out a functional global inside a lvlib, that wouldn't make sense and should be class) of that library.

Any thoughts/comments?

Ton

Link to comment

I can't say I've run into this particular problem, yet I'm fairly certain I've distributed reuse code using community scoped methods. It could be that I friended specific vis rather than an entire library. That's one work around. A possible (though ugly) work around is to edit .lvlib file and change the friend path to the location where you exepct the addon to be located.

[Later...]

Stepping back a bit and taking a broader view I think your deployment model is flawed. You're deploying the Api module first, then developing the extended Api (xApi) module as an addon against it. Even if you could define friends by name the addon developer would have to use your predefined name for the addon to work. That's not really addon-ish behavior. If the functions in Api and xApi are closely related they should be deployed together in a single module. Use virtual folders and sub palettes to segregate the xApi functions.

If they are different enough to warrant two separate deployment modules you might be able to achieve what you're after by restructuring your libraries. Create a project file that contains three libraries: Api.lvlib, xApi.lvlib, and Common.lvlib. Take all the community vis from Api and put them in Common. Make Api and xApi friends of Common. When you create builds for Api and xApi, the modules will each carry their own copy of Common, so to avoid cross linking you'll have to give the library unique names during the build.

I can understand how changing the linking to 'by name' may compromise the validity of classes (a friend might alter data)

I don't understand how linking by name instead of by path makes a friend more or less able to alter data. Can you explain?

Link to comment

I can't say I've run into this particular problem, yet I'm fairly certain I've distributed reuse code using community scoped methods. It could be that I friended specific vis rather than an entire library. ...

Could you describe that a little bit broader? I don't think you can select a specific VI as a friend.

Stepping back a bit and taking a broader view I think your deployment model is flawed. You're deploying the Api module first, then developing the extended Api (xApi) module as an addon against it. Even if you could define friends by name the addon developer would have to use your predefined name for the addon to work. That's not really addon-ish behavior. If the functions in Api and xApi are closely related they should be deployed together in a single module. Use virtual folders and sub palettes to segregate the xApi functions.

I did not say my system was perfect, when (yes, when not if :rolleyes:) NI decides make friends addressable by name, I would opt for a system with wildcards, so I could deploy a system of add-ons.

I would not say that xApi is deployd against xAPI, it is build on the API.

One of the benefits of a modular reuse library is that you can declare dependencies and be assured that the base library is always installed.

If they are different enough to warrant two separate deployment modules you might be able to achieve what you're after by restructuring your libraries. Create a project file that contains three libraries: Api.lvlib, xApi.lvlib, and Common.lvlib. Take all the community vis from Api and put them in Common. Make Api and xApi friends of Common. When you create builds for Api and xApi, the modules will each carry their own copy of Common, so to avoid cross linking you'll have to give the library unique names during the build.

I will explain a little broader what my goal is.

I built a public API (only lvlibs, no classes) that is a nice wrapper around a command line tool, I would like to make this libary public and share it with the community, anyone could build upon this library it's own tools. I have an advanced GUI in mind that uses this wrapper and would like to make some money out of this tool, and being the developer of the public API I have some deeper knowledge about hidden VIs, so I would like to give me the power to use these VIs, off-course I could export the VIs to the client tool, but IMHO is any doubling of code a NoNo.

I have run into a strange side effect of friends with paths that's not so nice:

-API.lvlib has declared xAPIt.lvlib and xAPI.lvlib as friends, xAPIt.lvlib is the name of my lvlib during development (t stands for temporary), xAPIt.lvlib is located in the development path, and xAPI.lvlib is located in user.lib

-Now I try to build xAPI.lvlib from source xAPIt.lvlib, during the build fase I get an error from the LabVIEW compiler, stating that a library of that name is allready in memory.

Which means that declaring a friend will cause LabVIEW to load it in memory... (xAPIt.lvlib called API.lvlib which refers to xAPI.lvlib).

That sounds really bad and support (IMO) that friends should not have paths.

I don't understand how linking by name instead of by path makes a friend more or less able to alter data. Can you explain?

I haven't reallys stepped into LVClasses, so rethinking what I said sounds silly indeed. Sorry.

Ton

Link to comment

I'm having similar ponderings regarding a toolkit I'm (was) working on.

I wanted to offer up basic functionality in one package and then enable building up on this for extensions to the framework. I also wanted to keep some dirty secrets for myself, so it pretty much mirrors the topic being discussed here.

IF we stick to the absolute naming, can we introduce new code levels (I'm using many classes) by allowing the declared friend also declare its own friends and thus expand the code base? I'm pretty sure I'm not expressing myself correctly... :wacko:

In other words, how do we make libraries portable yet extendable. A further issue is how to provide some pseudo-private functions (by abusing the friend mentality)?

Shane

Link to comment
  • 2 weeks later...

Been a while since I've been able to spend any significant time on the forum...

Could you describe that a little bit broader? I don't think you can select a specific VI as a friend.

Sure you can. Right click the library, Properties -> Friends -> Add Friend. Navigate to the VI you want to declare as a friend and click OK. Whether or not that will solve your problem is another question...

One of the benefits of a modular reuse library is that you can declare dependencies and be assured that the base library is always installed.

I agree modularity is good. Independent modules are far better than dependent modules.

IMHO is any doubling of code a NoNo.

I disagree. Sometimes duplicating code is a better solution than creating dependencies. Duplicating source code can easily cause problems. Duplicating deployed code in user.lib or vi.lib? Meh... as long as you do it smartly it's really not that big of a deal and avoids a lot of issues, especially if the duplicated code is private to the library that contains it.

and being the developer of the public API I have some deeper knowledge about hidden VIs, so I would like to give me the power to use these VIs

I don't think the technique you want to use is going to be very secure. Just remember, if you can create a library that becomes a friend of a library you've already developed and deployed, so can others. Those 'hidden' vis won't remain hidden for very long. If you're serious about protecting your IP create a single project with two builds: one for API.lvlib and one for xAPI.lvlib.

IF we stick to the absolute naming, can we introduce new code levels (I'm using many classes) by allowing the declared friend also declare its own friends and thus expand the code base?

Sure, at least I'm not aware of restrictions that prevent this, though I haven't tried it directly. Suppose ObjA friends ObjB, which in turn friends ObjC. ObjC will not be able to use ObjA's community methods directly. ObjB will have to wrap ObjA's community method in it's own community-scoped method. ObjC then uses ObjB:CommunityScopedMethod on its block diagrams.

In other words, how do we make libraries portable yet extendable.

Usually via inheritance or composition. (Neither of which apply to .lvlibs... sorry.)

A further issue is how to provide some pseudo-private functions (by abusing the friend mentality)?

Community scoped methods already are pseudo-private. Only very specific vis are allowed to use them. You and Ton are trying to make them more accessable than they already are. Maybe it is possible to deploy friend libraries after the fact. My gut sense is that it will create unexpected problems down the road.

Link to comment

One reason: Friends are not loaded into memory when the library loads. But for the security model to work, friends that actually take advantage of the friend relationship have to be marked so that we know that the password was properly supplied when the subVI was dropped. This prevents someone from creating a new file of the same name and swapping in new functionality under the guise of friendship. Thus, if you do "Save As:Rename" on the library, all the friends of that library need to load into memory to update that mark. The path lets the project do this loading.

There may be other reasons. I flagged this thread for Trevor since he's the primary developer of friend and community scope.

Link to comment

Classes in a project library (.lvlib) are extensible, even though the project library itself is not.

True, but it doesn't sound like that's what they are doing.

But for the security model to work, friends that actually take advantage of the friend relationship have to be marked so that we know that the password was properly supplied when the subVI was dropped. This prevents someone from creating a new file of the same name and swapping in new functionality under the guise of friendship.

I was wondering how (and if) you prevented that from happening. I take it this strict relationship is enforced even if the library isn't password protected?

Link to comment

My implementation of Friendship and Community scope was a year or two ago, so I may be fogging some details. Here I go anyway:

The library remembers the paths of its friended items because remembering the qualified name and path of a friend is free behavior provided by the foundational components that friendship was built on. I didn't foresee that there would be any problems with the existing behavior, so I didn't do any extra work to check only the qualified name of friends.

It would be possible to change this in the future, but it would make save for previous a little rough, and in general I don't like having subtle behavioral changes between versions of LabVIEW. Lets see if we can get the behavior you want in some other fashion. Some possibilities that come to mind are:

If you were willing to store your friended item in user.lib while it's being written, then when the friending library is saved I'd expect it to store the path '<user.lib>/foo/MyThing.lvlib'. When you deploy your value-added component, it would land in <user.lib> and everything should connect up fine without a crossload dialog, right?

If you write some kind of friended command-broker kind of VI that gets distributed with your library and accepts commands which it forwards to the rest of the library, you could require that commands passed to the broker also include some kind of password. You could lock the broker and add-on clients of the broker, and that would be roughly as secure as the friendship validation scheme already in place (the validation scheme already in place is good, but not professional-caliber-cryptography secure).

Do either of these options sound workable?

Link to comment

If you were willing to store your friended item in user.lib while it's being written, then when the friending library is saved I'd expect it to store the path '<user.lib>/foo/MyThing.lvlib'. When you deploy your value-added component, it would land in <user.lib> and everything should connect up fine without a crossload dialog, right?

That sounds like what I tried to do:

<user.lib>\a.lvlib is the main lvlib it has two friends:

  1. <user.lib>\b.lvlib
  2. c:\mydocs\bt.lvlib

I develop my code in bt.lvlib, and I tried to use the standard NI Source Distribution method, to rename c:\mydocs\bt.lvlib into c:\mydocs\built\b.lvlib, this however fails since 'the item is allready in memory', (note that a.lvlib is being used throught my code in LabVIEW tools that run in the background during development, but I have a feeling this is not the cause, could I have discovered a bug?). So this basically rules out using friendship for my in this case.

If you write some kind of friended command-broker kind of VI that gets distributed with your library and accepts commands which it forwards to the rest of the library, you could require that commands passed to the broker also include some kind of password. You could lock the broker and add-on clients of the broker, and that would be roughly as secure as the friendship validation scheme already in place (the validation scheme already in place is good, but not professional-caliber-cryptography secure).

That sounds like a gateway and is certainly valid, but a little bit too complicated for this case.

Ton

Link to comment

So if I don't apply a password to my community and friended components, it's possible for someone to swap in new functionality under the guise of friendship?

Yes. No different than replacing a subVI with another of the same name. What made this different -- and thus, why we made it securable -- is that you're opening up access scope to call into a normally off-limits function.
Link to comment

I develop my code in bt.lvlib, and I tried to use the standard NI Source Distribution method, to rename c:\mydocs\bt.lvlib into c:\mydocs\built\b.lvlib, this however fails since 'the item is allready in memory', (note that a.lvlib is being used throught my code in LabVIEW tools that run in the background during development, but I have a feeling this is not the cause, could I have discovered a bug?).

I would not expect friending an item to bring that item into memory. I suppose that renaming things in LabVIEW could have troubles if the thing is already in memory somewhere else. If you try the build in an environment without your additional tools installed, is it successful?

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
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
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.