ANN: PyKDE now does KDE plugins

Jim Bublitz jbublitzno at spamnwinternet.com
Fri Nov 7 23:21:50 EST 2003


John J. Lee wrote:

> Jim Bublitz <jbublitzno at spamnwinternet.com> writes:
> [...]
>> required. This is the first in what's planned to be a number
>> of extensions for PyKDE that allow plugins and related objects
>> to be created entirely in Python; David Boddie is nearing
>> release of modules for authoring KParts for export (PyKDE
>> already imports KParts), KDE Control Center modules, and
>> IOSlaves.
>> 
>> Future plans include allowing QWidget subclasses created in
>> Python to be imported into Qt Designer with complete
>> functionality, and possibly Python scripting and plugins for
>> KDE apps like KOffice and Kontact. The underlying mechanisms
>> and code are similar in all cases.
> [...]
> 
> Wow, sounds like impressive stuff.  How does it work?  Is there
> a standard .so proxy that can be used by all Python plugins? 

Basically yes - it's a little more convoluted than that. Panel
applets need a .desktop file which specifies the .so lib to
load. The .so specified is symlinked to the proxy, so it's
filename is correct and unique, but still runs the proxy code.
(There's a fake .la file in this case too, since the loader
expects one)

The .so proxy starts another .so that wraps the Python
interpreter, and from the config file name that the plugin
loader passes in it computes the name of the .py file. The .py
file is loaded into the interpreter, and the Python factory
function is located and called. That constructs the actual
applet (from Python via PyKDE/PyQt). A PyObject is returned to
the proxy .so which uses sip/PyKDE to convert it to a C++
pointer to the required type which is passed back to the loading
app.

The same scheme will work for almost any plugin - the major
difference is that in some cases the plugin loader doesn't
provide enough info to allow a proxy for the .so file (for
example, to load "somePlugin" the loader might expect
libsomePlugin with an init_somePlugin factory function in C++).
For those cases, the plan is to autogenerate the plugin-specific
.so file (naming is the only thing that varies), but it still
requires a C++ 'make" step.

For panel applets, there's an installer that does most of the
work (except for actually writing the py file) and does things
like validate and serve as a test harness. Plugins can be hard
to debug, and a failed load rarely returns any error info, so t
it's helpful to be able to run the plugin outside the loading
app.

It takes more lines than to describe than to implement - it
really isn't much code. David Boddie, who did a lot of the
development on panel applets has a bunch of other stuff coming
soon - KParts (including a Wiki KPart), IOSlaves, KDE Control
Center plugins. The same scheme will also work for styles,
QtDesigner plugins and apps that take plugins. Quite a while ago
I had a similar KSpread (KOffice spreadsheet) plugin working
using a cruder version of the same basic idea. Apps require a
Python wrapper for their API to be useful, but that's also
pretty simple to write using sip (for a well-written app
anyway).

> What sort of memory footprint do these plugins have?

The "Presidential" answer is: not very big at all. The real
answer is that by the time you load PyQt and the necessary PyKDE
modules you're up around 10MB or more I'd guess (plus other
shared libs that will already have been loaded). The Python
interpreter .so adds about another MB, the plugin code itself is
in Python and only maybe 5KB to a few hundred KB depending on
complexity. The proxy .so is very small too.

My opinion is that this is great for prototyping, but some people
are willing to spend that much memory to be able to do plugins
in Python. I had one applet running for a few weeks, and I'd
have to say that on a machine with 1GB of memory it isn't a big
deal, but I still find it a little mind-boggling - maybe 20X
what the original IBM PC came with just to run a 40x40 pixel
panel applet.

There's a couple places I find this really worthwhile though - if
you're writing an app with PyQt/PyKDE in the first place or
regularly have an app running based on those, the memory cost is
minimal because it's all in shared libs. The other really useful
place is a situation like the spreadsheet plugin I mentioned -
it only took about 2MB total and allowed all kinds of stuff the
app itself couldn't do (eg manipulate a spreadsheet in the
background). That's based on a thin wrapper instead of a
complete set of bindings and no GUI programming in the plugin
(basically no PyQt or PyKDE).
 
>> In some cases, specific .so libs will still be required
>> (depends on the plugin loader), but the Python modules will
>> include autogeneration of the necessary C++ code, along with
>> installers to simplify the task of making the plugins
>> available.
 
> What makes the difference between all-Python and needing a bit
> of C++ here?

Just what the app loading the plugin expects to find. If the
factory or init function of the plugin is uniquely named, there
isn't a convenient way to intercept the call - well there
probably is, but I haven't figured it out yet. If someone knows
more about .so loading and structure than I do and sees a
solution I'd be interested in hearing about it. I'm sure there
must be a way to hack the .so's symbol table or some such, but
it's beyond me at them moment. I suppose if the parameters
passed to the plugin don't convey the necessary info, that would
be another case, but I don't think that occurs in KDE or Qt.

On the other hand, there's really no reason why a proxy wouldn't
*always* work if C++ developers allowed for it - always call a
factory function with the same name ("init", "create". whatever)
and pass in an identifying string for locating the plugin.
Probably makes C++ plugins a little harder to write though.

Jim





More information about the Python-list mailing list