Re: Glib::Module



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() ;
}


Bart Verstraete wrote:

Hi here follows the samplecode and the question is. I get no errors, it seems to load the moduleeee only when I try to acces the function via get_symbol() the sample app print this:
Name of the plugin: plugins/sample.dll
Error: `action': The specified procedure could not be found.





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]