Re: Glib::Module
- From: Bart Verstraete <bartverstraete telenet be>
- To: Paul Davis <pjdavis engineering uiowa edu>
- Cc: gtkmm-list gnome org
- Subject: Re: Glib::Module
- Date: Sat, 24 Sep 2005 12:04:29 +0200
Hi,
Why would Glib::Module exist if it isn't usable? And if I am correct
your talking of linux enviroment and I am developing on a windows
machine. But that wouldn't be a problem if you use Glib::Module. I want
to port my app to llinux when I am done thats why I use xxxmm where I
can. And C++ because its easy readable. I think there wasn't one line of
my (somewhat stupid) code you did't understand. For starters what does
the python script? Is that realy needed for a c++ progrram? What you say
about the standard search paths, why would it, I said my app loads the
module correct with no error when I call 'get_last_error()' only the
get_symbol() calling doesn't work. And please never but never again say
'that can't be done in c++' because everything that in c can be done in c++!
This wasn't to offend you. Ok. But I gone decode your app :d and if I
get it to work I gone let you know. Alsoo thx for your reply!
grts Bart
Paul Davis wrote:
Bart,
From what I know about plugins, all symbols that you lookup should be
C names. Using C++ classes as names and such is a no no. The work
around is to define a method that just calls new Plugin()
I kind of hacked your code to get things situated correctly. Now
obviously this isn't nearly as fleshed out as it should be. I'm in
the middle of writing my own plugin loader and I'll post a link to it
when I get finished with that.
Glib::Module appears to be a very thinly veiled wrapper around libdl.
I haven't groked the source or anything, but the api is rather
similar. The passing a void*& pointer reference through me for a few
minutes but it all works.
Note that the tricky part is how you use the loaded symbol. You've
got to cast from void* to a function pointer. The syntax is a bit
weird, but here its the line:
Plugin* ( * LoadPlugin ) () ;
This declares LoadPlugin as a pointer to a function with signature:
Plugin* FUNCTION_NAME() ;
And then its just a matter of passing it to get_symbol by casting it
to void*&
Things to mention:
The loader should automatically guess the extension of the file your
loading. This makes things "portable". Ewww.
Notice the call Glib::Module::build_path( string directory, string
name ). This even adds the lib prefix.
Glancing at the Glib::Module docs, it looks like it searches standard
search paths, ie /lib, /usr/lib. I know with libdl you can add to
these search paths to try and make your plugin findable. I never
really got it to work and its probably a better idea to use fully
qualified paths for security's sake.
Thats all I really have to say about that.
yay.
There *could* be a downfall to the way I'm doing this, but I think it
should work. If you try and load more than one plugin I don't know if
the defined LoadPlugin name will conflict. It would be easy enough to
write a second example plugin and load it as well. that should tell
you if its working.
Hope this helps anyone that cares.
Here's the code. I've included the scons build files just to point
out how trivial it makes things like this. Imagine trying to paste
the volumes of atuomake/autoconf stuff here. Get scons at
www.scons.org. The only dependancy is python > 1.5.(2 or 3) which was
in version 7.2 or so of Red Hat which was a long time ago. Enough
preaching.
So here it is.
The directory layout:
./SConstruct
./main.cpp
./base_plugin.hh
./plugins/
./plugins/SConscript
./plugins/sampleplugin.cpp
/*
*
* ./Sconscript
*
*/
# vim: ft=python
env = Environment()
env.ParseConfig( 'pkg-config gtkmm-2.4 --cflags --libs' )
Export( 'env' )
env.Program( 'PluginTest', 'main.cpp' )
SConscript( 'plugins/SConscript' )
/*
*
* ./main.cpp
*
*/
#include <string>
using std::string ;
#include <iostream>
#include <glibmm/module.h>
#include "base_plugin.hh"
int main( int argc, char* argv[] )
{
if( argc != 2 )
{
fprintf( stderr, "usage: %s <plugin_name>\n" ) ;
return -1 ;
}
Plugin* ( * LoadPlugin ) () ;
Glib::Module plugin( argv[1] );
if( !plugin )
{
fprintf( stderr, "Failed to load plugin: %s :: %s\n", argv[1],
plugin.get_last_error().c_str() ) ;
}
else
{
fprintf( stderr, "Loaded plugin: %s\n",
plugin.get_name().c_str() ) ;
if( plugin.get_symbol( string( "LoadPlugin" ) , ( void*& )
LoadPlugin ) )
{
Plugin* loaded_plugin = LoadPlugin() ;
fprintf( stderr, "What does the plugin return? : %d\n",
loaded_plugin->action() ) ;
}
else
{
fprintf( stderr, "Failed to find plugin creation symbol.\n"
) ;
}
}
return 0;
}
/*
*
* ./base_plugin.hh
*
*/
#ifndef TESTPLUGINAPP_GENERIC_H
#define TESTPLUGINAPP_GENERIC_H
#define BEGIN_C_DECLS extern "C" {
#define END_C_DECLS }
class Plugin
{
public:
virtual int action() = 0;
};
BEGIN_C_DECLS
Plugin*
LoadPlugin() ;
END_C_DECLS
#endif //TESTPLUGINAPP_GENERIC_H
/*
*
* ./plugins/SConscript
*
*/
# vim: ft=python
Import( 'env' )
env.SharedLibrary( 'sampleplugin.cpp' )
/*
*
* ./plugins/sampleplugin.cpp
*
*/
#include "../base_plugin.hh"
#include <iostream>
class SamplePlugin : public Plugin
{
public:
int action()
{
fprintf( stderr, "Returning 9 from sample
plugin.\n" ) ;
return 9 ;
}
} ;
Plugin*
LoadPlugin()
{
return new SamplePlugin() ;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]