Re: plugins in a delphi program?
From: Maarten Wiltink (maarten_at_kittensandcats.net)
Date: 03/15/04
- Next message: Jud McCranie: ""read only" XP vs. 2000"
- Previous message: Maarten Wiltink: "Re: subject: a bug or a feature? const in D-6"
- In reply to: Nicolai Hansen: "plugins in a delphi program?"
- Next in thread: Nicolai Hansen: "Re: plugins in a delphi program?"
- Reply: Nicolai Hansen: "Re: plugins in a delphi program?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Mon, 15 Mar 2004 23:10:41 +0100
"Nicolai Hansen" <nic@aub.dk> wrote in message
news:d96764ff.0403150658.367a48d9@posting.google.com...
> Hi NG !
>
> I am thinking about a better way to do this huge program we are
> programming at work when we need the next version :)
>
> I am thinking about making it a core program with a lot of optional
> modules (plugins) which could be installed just as files in the
> program folder.
[...]
> Something like that - any advise?
Lots. Been there, done that. It even worked.
First, you need to bind a plugin into your program, so its functions
are accessible through the UI. I used a scheme where a DLL exported
two functions, Execute and Update. The latter was really named Affect,
but you get the idea - it was effectively an Action. The plugin did
not concern itself with binding into the GUI at all; this was handled
by a non-visual component on the host form. It had properties for
which DLL to load, and for the menuitem to add an item after and for
the toolbutton to add a button next to. This restricted GUI access to
plugin functions to the menu and toolbars, but that never bothered me.
After awhile, I had an endless row of pictures of little Swiss knives
with little saw blades being fitted into them on my form, and rewrote
it to create all the plugin components dynamically, at application
startup, from information in the Registry. After detaching the
integration information from the plugin, this also more or less detached
it from the host application. I consider this a good thing. Rather than
taking all the integration information from the plugin (possibly ending
up with menu items in English in an otherwise Dutch-language program),
or having to specify it all at design-time, it lets you set everything
dynamically. If you want, you can even dynamically load and unload the
plugins under user control, while the host application is running.
(I thought about this, but never got around to it. It wasn't that
important, either, just a nice idea to drive home the point that this
was really incredibly flexible.)
The second problem is data exchange between the host application and
the plugin. It took me some time to realise that the host application
determines the plugin interface, and all plugin components in the same
host application should use the same event handlers.
These event handlers were four in number, one to query parameters from
the host application and three to return results to it. In the parameter
querying event, the plugin passes a TList to the host application, which
places information in it that the plugin can use. I sent references to
the plugin's menuitem and its toolbutton, so that the Update procedure
in the plugin DLL could change their state as appropriate (remember,
this was before Actions), and a number of objects that described the
application state to the plugin. The application was an editor for
quite involved data structures and I passed references to the entire
document object and to the subobject that was currently selected.
Three types of information could be returned to the host application:
either an object, a number, or a string. The plugin DLL's Execute
function returned an Integer; the call was made as a procedure call
through the plugin component and if the integer value of the return
value from Execute was below 32, it fired the integer-return event;
otherwise the value was interpreted as an object reference. The
string-return event was fired in case of an exception.
Looking back, knowing of actions would have made things much clearer.
A plugin can simply be viewed as a delegated action, supplying the
OnExecute and OnUpdate handlers for a local action. Because the plugin,
specifically the exported routines in the DLL, are in a different
module, the calls have to be decorated with parameters and return
values as they don't have access to the full application state. The
parameters depend on the host application; access to the GUI binding
components is the common ground they all share. Today, passing in the
local (delegating) action is the easiest way for that. The remaining
parameters should make the application state fully accessible to the
plugin. In my style of programming, applications tend to work on a
single, complex object, so this "document" object is the prime
candidate for passing to the plugin. Some way to indicate the focus
position is usually also required; how this is done and in what detail
depends on and varies greatly with the application.
Groetjes,
Maarten Wiltink
- Next message: Jud McCranie: ""read only" XP vs. 2000"
- Previous message: Maarten Wiltink: "Re: subject: a bug or a feature? const in D-6"
- In reply to: Nicolai Hansen: "plugins in a delphi program?"
- Next in thread: Nicolai Hansen: "Re: plugins in a delphi program?"
- Reply: Nicolai Hansen: "Re: plugins in a delphi program?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]