Re: Glib::Module



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]