Jump to content

Plugins & projects


Recommended Posts

Hi!

The LabVIEW 2010 (10.0f2) project I'm working on, is a fairly big program for controlling a couple of setups in our scientific laboratory (about 500 VIs and a dozen classes — might be quite small in some people's eyes, but anyway). To make it easier for people to add their own functionality to the program without having to dig into the full project, I've decided to try and implement a plugin system. Things seem to be working pretty well, but I'd really like some advice about how I should organize my files in (sub)projects etc.

I've looked around to find out what would be a good way to do this, and have ended up doing the following — which seems to be a fairly standard way of implementing this in LV:

  • I created a "Plugin Interface" LV class, which has some basic functionality, as well as a few 'abstract method VIs' that need to be overrided by descendants.
  • Plugins are loaded from a specific location. Each plugin is a LV class that descends from "Plugin Interface.lvclass". It implements the abstract method VIs.
  • The main program calls the various methods of the plugin when necessary.

Nothing new thus far.
Let's say now that I'd like to write a plugin, without affecting the main project structure. My idea was to:
  • Let the plugin directory be external to the main project. (E.g., main project in "D:\Dev\My Project\Main", and plugin directory in "D:\Dev\My Project\Plugins").
  • Let each plugin be its own project file, defining one LV class. (E.g., plugin in "D:\Dev\My Project\Plugins\My Plugin\My Plugin.lvclass", in the corresponding project "D:\Dev\My Project\My Plugin\My Plugin.lvproj").

See the following picture:

bW6OL.png

Now I can keep the "Main" project under version control, separately from the various plugins.

My main problems are:

(1) If I want "My Plugin.lvclass" to inherit from "Plugin Interface.lvclass", I cannot do this unless I somehow add "Plugin Interface.lvclass" to "My Plugin.lvproj".

(1a) If I directly add "Main\Plugin Interface.lvclass" to "My Plugin.lvproj", and then start implementing the abstract methods from "Plugin Interface.lvclass", I get the following error message as soon as I try to save a method VI: "Fatal Internal Error: "OMUDClassLinker.cpp", line 4161".

(1b) Manually adding a dependency on "Plugin Interface.lvclass" to "My Plugin.lvproj", instead of the class itself, doesn't seem possible.

(1c) The other method would be, I guess, to just *copy* the "Plugin Interface.lvclass" file to the "My Plugin" project. That would create a huge mess, though...

And, more generally:

(2) Is this a good way to organize things in the first place? Are there better ways to organize my plugin files into more or less separate packages? Would it be possible to solve this using Project Libraries?

Thanks a lot for your time; I'm looking forward to hearing about your insights!

Sincerely,

Onno

Link to comment

(1a) If I directly add "Main\Plugin Interface.lvclass" to "My Plugin.lvproj", and then start implementing the abstract methods from "Plugin Interface.lvclass", I get the following error message as soon as I try to save a method VI: "Fatal Internal Error: "OMUDClassLinker.cpp", line 4161".

I'm going to ignore the rest of your post (others can help out with plugin setup) and focus on the one part that you probably need NI help to resolve. That error you describe should simply not happen. Ever. Any chance I can get you to post VIs that replicate this?

Link to comment

An excellent topic!

(1) If I want "My Plugin.lvclass" to inherit from "Plugin Interface.lvclass", I cannot do this unless I somehow add "Plugin Interface.lvclass" to "My Plugin.lvproj".

Well, you *can*, but it's a little unintuative. You can create a class that exists in the parent project, and then manually copy it to a new location to create a new instance (like a template, if you will). Then load your plugins dynamically by filepath. The trick is that when you deploy the new plugin, you'll need to build a source distribution first, then an installer, which means that some files of the parent installation will be overwritten, but as they're the same file, it's okay.

(2) Is this a good way to organize things in the first place? Are there better ways to organize my plugin files into more or less separate packages? Would it be possible to solve this using Project Libraries?

I think the approach above is fine. We have a couple of projects that have parent and child classes (ie: plugins) exist completely separately and (once we worked out the difficulties of distribution) it works great.

Well, you *can*, but it's a little unintuative. You can create a class that exists in the parent project, and then manually copy it to a new location to create a new instance (like a template, if you will). Then load your plugins dynamically by filepath. The trick is that when you deploy the new plugin, you'll need to build a source distribution first, then an installer, which means that some files of the parent installation will be overwritten, but as they're the same file, it's okay.

This is what I'm talking about:

post-181-0-06565900-1296844016_thumb.gif

Link to comment

I'm going to ignore the rest of your post (others can help out with plugin setup) and focus on the one part that you probably need NI help to resolve. That error you describe should simply not happen. Ever. Any chance I can get you to post VIs that replicate this?

Yeah, sure. I had been considering to do that for my original post, but didn't have the time. I'll see if I can reproduce this error in a small test project. May take some time, though, so don't hold your breath ;-)

Thanks a lot for your reply!

Thanks a lot for your input, I appreciate it!

Well, you *can*, but it's a little unintuative. You can create a class that exists in the parent project, and then manually copy it to a new location to create a new instance (like a template, if you will). Then load your plugins dynamically by filepath. The trick is that when you deploy the new plugin, you'll need to build a source distribution first, then an installer, which means that some files of the parent installation will be overwritten, but as they're the same file, it's okay.

Hm, I'm not sure I fully understand, so let me see. Do you mean:

  • I copy "Plugin Interface.lvclass" to the directory "Plugins" (referring to my original tree picture);
  • I let "My Plugin.lvclass" inherit from this copied "Plugin Interface.lvclass".
  • When I create my source distribution, the paths will work out fine since the copied "Plugin Interface.lvclass" (and associated VIs) overwrite the exact same "Plugin Interface.lvclass" that is part of the Main project.

Am I right? If so, I think it's a great trick. It does have a few drawbacks, though:
  • It assumes my colleagues will go to the trouble of creating installers for their plugins. Given the hackaway nature of the work in my group (as in many small physics labs, in my experience), I doubt people will do that.
  • I have to make copies of "Plugin Interface.lvclass". Although the Main project is in source control, this can still lead to some nasty issues, I suppose.

Any other ideas that could work around this? I imagine that you could just forget about copying the duplicate "Plugin Interface.lvclass" at all, as long as you make sure the relative paths are the same?

Link to comment

Stupid question. Why does your plugin class have to be in a separate project? Your statement: "To make it easier for people to add their own functionality to the program without having to dig into the full project" is not clear to me.

Which class is the reusable component? Classes are libraries and libraries are by design meant to be reused.

Link to comment

Why does your plugin class have to be in a separate project? Your statement: "To make it easier for people to add their own functionality to the program without having to dig into the full project" is not clear to me.

Good question actually. My thought was that I'd rather not have people add their plugin code to the Main project. There will likely be quite a few plugins floating around in the group, and I don't want code changes in those plugins to affect the main project. Does that make any sense?

The workflow I had envisioned, would go like this: someone checks out the Main project from source control. He then creates a separate project for his plugin (based on a template). He can then go and write his plugin, save the plugin code into his own version control, etc. However, the Main project doesn't change (the plugin files are not added to the Main project file), so I avoid having to deal with lots of commits from other people in the group.

Which class is the reusable component? Classes are libraries and libraries are by design meant to be reused.

What do you mean by "reusable component"? In any case, the "Plugin Interface" class is the class that plugins derive from. Does that answer your question?

Sincerely,

Onno

Link to comment

The workflow I had envisioned, would go like this: someone checks out the Main project from source control. He then creates a separate project for his plugin (based on a template). He can then go and write his plugin, save the plugin code into his own version control, etc. However, the Main project doesn't change (the plugin files are not added to the Main project file), so I avoid having to deal with lots of commits from other people in the group.

This is why we need a project manager (read project/class/lvlib manager) that can nest projects like any other language can. At present, we can only include sub-components at one level down the dependent tree. This means that in your (and my) cases if your component also shares reusable code, that code cannot be used higher up the hierarchy (or so it seems).

We have lost one of the big benefits of LV in that if a VI is in memory, it is automatically used (without winge-ing that x owns y or breaking VIs). If you want easily distributable (slim) components. Don't use the project manager or lvlib -. Use a VI tree.vi.

Link to comment

(1a) If I directly add "Main\Plugin Interface.lvclass" to "My Plugin.lvproj", and then start implementing the abstract methods from "Plugin Interface.lvclass", I get the following error message as soon as I try to save a method VI: "Fatal Internal Error: "OMUDClassLinker.cpp", line 4161".

Well, er... It seems I cannot reproduce this error — not even in the original project. I guess LabVIEW was fried when I tried this last Friday. I'll remember for next time that I'll first restart my computer before posting something like this :) My apologies to Aristos!

Anyway, this means that my problem is more or less solved now: I can put my plugins in separate projects.

As a sidenode: the trick for only getting a dependency on "Plugin Interface.lvclass", without adding the file itself to the Plugin project, is the following:

  1. Add "Plugin Interface.lvclass" from the Main project to the Plugin project, by "adding an existing file" in the Project Explorer. "Plugin Interface.lvclass" will now be in both Main and Plugin.
  2. Create your descendant class. (This is not possible if you haven't done step 1, as you can only choose parent classes that are part of the current project).
  3. Now remove the "Plugin Interface.lvclass" from the Plugin project again. LV will automatically add "Plugin Interface.lvclass" to the Plugin project's dependencies.
  4. Done!

Link to comment

I'm a little confused as to why you can't just leave the "Plugin Interface.lvclass" in two or more projects. Projects don't claim ownership of items, the lvclass should not be modified by inclusion into the project*. By using a source code distribution, can't you just place your base class external to your executable, and have all your built-in interfaces inherit from the external class, as will any interfaces built outside the context of your project?

*There are definite bugs that cause class attributes or methods to be modified when working on descendant classes, I can't deny that...I just always revert those with source code control.

Link to comment

*There are definite bugs that cause class attributes or methods to be modified when working on descendant classes, I can't deny that...I just always revert those with source code control.

I've never replicated any claim regarding this. There is no code that I can find that would cause this. Do you have VIs that replicate this?
Link to comment

I've never replicated any claim regarding this. There is no code that I can find that would cause this. Do you have VIs that replicate this?

I'm aware I "owe" you an example, I have not been able to narrow it down to a concise list of steps to reproduce. I work with a re-use library in which I extend its classes in multiple projects, all I can say at this point is it's at least a weekly occurrence where a base class member in the library will get modified for some reason and I revert. It's always a dynamic dispatch method and occasionally the lvclass itself, beyond that I have not been able to pin it down. I suspect it's related to property nodes, but again, that's just a guess, and I don't want to send this topic off on a tangent...

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.