Author Topic: Inter-Plugin communication  (Read 10954 times)

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Inter-Plugin communication
« on: June 10, 2007, 02:06:29 pm »
As some of you know, I'm working on two plugins and plan to make one depend on the other. Obviously, the dependant plugin needs to check if the other is available before attaching itself (or at least before making calls to the first plugins API). How would I do this?

wxLearner

  • Guest
Re: Inter-Plugin communication
« Reply #1 on: June 10, 2007, 02:26:54 pm »
Hello,
I think, LibLoader::LoadLibrary can be used to get a pointer to a wxDynamicLibrary object. If the plugin is already loaded LibLoader::LoadLibrary will return it, else it will create a new wxDynamicLibrary object and try to load the plugin. Then you can check, if the plugin was loaded by using the wxDynamicLibrary object's IsLoaded method, like PluginManager::LoadPlugin does.

LibLoader::LoadLibrary and PluginManager::LoadPlugin are defined in sdk/pluginmanager.cpp

Thank you, for making Code::Blocks even greater :D

EDIT:
Sometimes I think too complicated!
It looks like it's enough, just to use PluginManager::LoadPlugin, which returns true, if the plugin has been loaded.
« Last Edit: June 10, 2007, 02:38:30 pm by wxLearner »

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: Inter-Plugin communication
« Reply #2 on: June 10, 2007, 04:25:58 pm »
thanks wxLearner.

Offline byo

  • Plugin developer
  • Lives here!
  • ****
  • Posts: 837
Re: Inter-Plugin communication
« Reply #3 on: June 10, 2007, 07:31:38 pm »
Hello,
I think, LibLoader::LoadLibrary can be used to get a pointer to a wxDynamicLibrary object. If the plugin is already loaded LibLoader::LoadLibrary will return it, else it will create a new wxDynamicLibrary object and try to load the plugin. Then you can check, if the plugin was loaded by using the wxDynamicLibrary object's IsLoaded method, like PluginManager::LoadPlugin does.

LibLoader::LoadLibrary and PluginManager::LoadPlugin are defined in sdk/pluginmanager.cpp

Thank you, for making Code::Blocks even greater :D

EDIT:
Sometimes I think too complicated!
It looks like it's enough, just to use PluginManager::LoadPlugin, which returns true, if the plugin has been loaded.

You should not use LoadLibrary because it may cause some problems that C::B can't handle for now. Generally plugins must be loaded from PluginLoader and probably inside it's scanning procedures. And any other library-loading code (even when you plugin imports some symbols from other one) will fail sooner or later.

You can see how it's done inside wxSmith and wxSmithContribItems plugins. They "communicate" together - wxSmithContribItems extends functionality of wxSmith. To make it work, I had to create extra dll which is not a plugin and resides in main C::B folder. The structure is like this:


wxSmith plugin                      wxSmithContribItems plugin
            \                     /
           uses                 uses
              \                /
              wxSmith shared library (not a plugin)


Such solution (by using external library) is best I've found so far. And for some reasons it's the only acceptable when you'll want your plugin to work on MAC.

Regards
   BYO

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: Inter-Plugin communication
« Reply #4 on: June 11, 2007, 04:02:37 am »
thanks byo. I'll think about this approach.

now, In addition to dependencies between my own plugins I was planning to use the env vars plugin to allow the activation of environment variables for each "interpreter" action. Based on what byo is telling me this isn't possible??

Offline byo

  • Plugin developer
  • Lives here!
  • ****
  • Posts: 837
Re: Inter-Plugin communication
« Reply #5 on: June 11, 2007, 10:43:22 am »
thanks byo. I'll think about this approach.

now, In addition to dependencies between my own plugins I was planning to use the env vars plugin to allow the activation of environment variables for each "interpreter" action. Based on what byo is telling me this isn't possible??

This may be a problem. You could obtain pointer to plugin by calling
Code
PluginManager::Get()->FindPluginByName(<PLUGIN NAME>);
It won't force C::B to load plugin's dll so it's safe but it won't work (on windows) because plugin's dll doesn't export EnvVars::GetProjectEnvvarSet and EnvVars::SetProjectEnvvarSet. Linker won't be able to link your plugin. And even if those symbols would be exported, your plugin would link to EnvVars dll so we have bad cross-plugin situation and it won't work :(.

Maybe it could be done through scripting system? (That's the way wxSmith communicates with ScriptedWizard plugin). But you will have to ask the maintainer of EnvVars plugin (MortenMacFly IIRC) to register few functions in scripting engine (I can help him because I've done it before ;) it's quite easy).

This cross-plugin linking problems should be fixed in future, but rather not before stable release :/

Regards
  BYO

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: Inter-Plugin communication
« Reply #6 on: June 11, 2007, 03:13:28 pm »
thanks again byo.

morten, any thoughts?

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: Inter-Plugin communication
« Reply #7 on: May 23, 2008, 04:15:59 pm »
bringing up this old thread again...

I've implemented a plugin structure that accesses a shared library along the lines that byo advocated:


plugin #1                      plugin #2
            \                     /
           uses                 uses
              \                /
              shared library (not a plugin)


I want to be able to deploy binaries of these plugins as .cbplugin files that the user can install from codeblocks. The question is how should I deploy the shared library? The shared library would normally be installed to the codeblocks binary directory (that's what byo does for the wxsmith plugins), but .cbplugin files won't deploy the binaries to that location. Can the shared library be installed to the plugins folder instead? (will it be found there??)

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: Inter-Plugin communication
« Reply #8 on: June 29, 2008, 02:20:22 pm »
byo? mandrav? anyone? (see  previous post) i guess if my plugins become a part of contrib there won't be an issue, but it would be nice if they were individually deployable using the current cbplugin blobs.

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Inter-Plugin communication
« Reply #9 on: June 29, 2008, 05:20:27 pm »
The shared library would normally be installed to the codeblocks binary directory (that's what byo does for the wxsmith plugins), but .cbplugin files won't deploy the binaries to that location. Can the shared library be installed to the plugins folder instead? (will it be found there??)
It will work if you load the library using LoadLibrary or the corresponding wxWidgets wrapper function and if you provide a full pathname. Configmanager::GetFolder(sdPluginsGlobal) should help you to figure out the full path.

Otherwise, the OS will look in its library path, whatever that may be, and will bail out. The Code::Blocks plugin folder is almost guaranteed to be not in the OS library path (except if a user explicitely added it, but why would anyone).
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline dmoore

  • Developer
  • Lives here!
  • *****
  • Posts: 1576
Re: Inter-Plugin communication
« Reply #10 on: June 29, 2008, 06:49:21 pm »
Thomas: thanks ... that sounds sensible

but, some questions:
1. Will I need to compile/link my plugins differently? I'm concerned that the OS will try to load the shared lib and fail before I make the manual load call. (I obviously don't know enough about how share libs work). My plugins define a static instance of a subclass based on classes in the shared lib (I'm using the same registration approach that C::B uses for the plugins)
2. Can each plugin call LoadLibrary? (does it matter if there is an attempt to load it when the lib has already been loaded)

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Inter-Plugin communication
« Reply #11 on: June 29, 2008, 08:13:13 pm »
ad 1.:
You cannot link to the library (or its import library) since that will cause an error 0x0000000c (or was it 0x0000005...?) at load time. If you link to a library, then the OS must be able to find it.
Therefore, what you have to do is this: You load the library manually, and then you set up function pointers for all functions you want to use. You initialise those using GetProcAddress (or a similar function). If you have worked with OpenGL before, you know the procedere, it's identical to loading OpenGL extensions.

ad 2.:
Yes, because LoadLibrary (and dlopen likewise) perform reference counting. They load every library exactly once and free the library when all processes that use it have unloaded it or have terminated.
If several processes load the same library, they normally share the physical memory of all readonly pages and treat the rest with copy-on-write semantics. The applications don't know about that due to virtual addresses (it "just works"). Anyway, since your two plugins run inside the same process space, this isn't an issue in any case.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."