]> Creatis software - cpPlugins.git/blobdiff - lib/cpPlugins/Interface.cxx
...
[cpPlugins.git] / lib / cpPlugins / Interface.cxx
index 0ee1faf9911aea516acf2fbe49c3d57a7c744930..53b7b118174179807139737986a54f5e9a1ed93b 100644 (file)
@@ -1,9 +1,12 @@
 #include <cpPlugins/Interface.h>
 
 #ifdef cpPlugins_SYS_WINDOWS
+#  include <Windows.h>
 #else // cpPlugins_SYS_WINDOWS
 #  include <dlfcn.h>
 #endif // cpPlugins_SYS_WINDOWS
+#include <cpPlugins_dirent.h>
+#include <algorithm>
 
 // -------------------------------------------------------------------------
 cpPlugins::Interface::
@@ -26,17 +29,80 @@ GetFilters( )
   return( this->m_Filters );
 }
 
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::
+GuessAccesiblePlugins( )
+{
+  // Load environment configuration
+  char* path = std::getenv( "cpPlugins_PATHS" );
+  if( path != NULL )
+  {
+    std::vector< std::string > tokens;
+    cpPlugins::TokenizeString( tokens, path, "#" );
+    for( auto tIt = tokens.begin( ); tIt != tokens.end( ); ++tIt )
+      try { this->LoadPluginDir( *tIt ); } catch( ... ) { }
+
+  } // fi
+
+  // Load local path
+  auto lpath = cpPlugins::CanonicalPath( "." );
+  try { this->LoadPluginDir( lpath ); } catch( ... ) { }
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::
+LoadConfiguration( const std::string& filename )
+{
+  std::ifstream in( filename.c_str( ) );
+  if( !in )
+    return( false );
+
+  this->UnloadAll( );
+  std::string line;
+  while( std::getline( in, line ) )
+    try { this->LoadPluginFile( line ); } catch( ... ) { }
+  return( true );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::
+SaveConfiguration( const std::string& filename ) const
+{
+  std::ofstream out( filename.c_str( ) );
+  if( !out )
+    return( false );
+  auto dIt = this->m_DynLibraries.begin( );
+  for( ; dIt != this->m_DynLibraries.end( ); ++dIt )
+    out << dIt->first << std::endl;
+  out.close( );
+  return( true );
+}
+
 // -------------------------------------------------------------------------
 void cpPlugins::Interface::
 LoadPluginFile( const std::string& filename )
 {
   // Open library with its canonical path name
   auto canonical_fn = cpPlugins::PathHelper::CanonicalPath( filename );
+  if( canonical_fn == "" )
+    throw std::runtime_error(
+      std::string( "cpPlugins::Interface: Library \"" ) +
+      filename +
+      std::string( "\" does not exist." )
+      );
+
+  // Check if it was already loaded
+  if(
+    this->m_DynLibraries.find( canonical_fn ) != this->m_DynLibraries.end( )
+    )
+    return;
+
+  // Ok, try to load the library
   void* hnd = Self::_DLOpen( canonical_fn );
   if( hnd == NULL )
     throw std::runtime_error(
       std::string( "cpPlugins::Interface: Could not load library \"" ) +
-      canonical_fn +
+      filename +
       std::string( "\"" )
       );
 
@@ -64,7 +130,7 @@ LoadPluginFile( const std::string& filename )
       if( new_filter )
       {
         // Update filters container
-        TCreator creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
+        auto creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
         if( creator != NULL )
         {
           this->m_DynFilters[ catIt->first][ *clsIt ] =
@@ -87,6 +153,39 @@ LoadPluginFile( const std::string& filename )
     Self::_DLClose( hnd );
 }
 
+// -------------------------------------------------------------------------
+unsigned int cpPlugins::Interface::
+LoadPluginDir( const std::string& dirname )
+{
+  DIR* dir;
+  struct dirent* ent;
+  unsigned int count = 0;
+  if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
+  {
+    while( ( ent = readdir( dir ) ) != NULL )
+    {
+      try
+      {
+        this->LoadPluginFile(
+          dirname +
+          std::string( "/" ) +
+          ent->d_name
+          );
+        count++;
+      }
+      catch( ... ) { }
+
+    } // elihw
+    closedir( dir );
+  }
+  else
+    throw std::runtime_error(
+      std::string( "cpPlugins::Interface: Could not load directory " ) +
+      std::string( "\"" ) +  dirname + std::string( "\"" )
+      );
+  return( count );
+}
+
 // -------------------------------------------------------------------------
 void cpPlugins::Interface::
 UnloadAll( )
@@ -106,13 +205,16 @@ UnloadAll( )
 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
 Create( const std::string& category, const std::string& name )
 {
-  cpPlugins::ProcessObject::Pointer filter = NULL;
+  typedef cpPlugins::ProcessObject::Pointer _TPointer;
+  _TPointer filter = NULL;
   auto catIt = this->m_DynFilters.find( category );
   if( catIt != this->m_DynFilters.end( ) )
   {
     auto clsIt = catIt->second.find( name );
     if( clsIt != catIt->second.end( ) )
-      filter = clsIt->second.second( );
+      filter =
+        ( reinterpret_cast< _TPointer* >( clsIt->second.second( ) ) )->
+        GetPointer( );
 
   } // fi
   return( filter );
@@ -124,7 +226,7 @@ _DLOpen( const std::string& fname )
 {
   void* hnd = NULL;
 #ifdef cpPlugins_SYS_WINDOWS
-  // TODO:
+  hnd = ::LoadLibraryA( fname.c_str( ) );
 #else // cpPlugins_SYS_WINDOWS
   hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
   dlerror( );
@@ -137,25 +239,40 @@ cpPlugins::Interface::
 TFilters cpPlugins::Interface::
 _DLGetFilters( void* hnd )
 {
-  TFilters filters;
+  // Get descriptors
+  typedef const char* ( *f_t )( );
+  f_t f = NULL;
 #ifdef cpPlugins_SYS_WINDOWS
-  // TODO:
+  f = ( f_t )( ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" ) );
 #else // cpPlugins_SYS_WINDOWS
-  typedef const TFilters ( *f_t )( );
-  auto f = ( f_t ) dlsym( hnd, "cpPlugins_LoadedFilters" );
-  const char* err = dlerror( );
-  if( err != NULL )
+  f = ( f_t )( dlsym( hnd, "cpPlugins_LoadedFilters" ) );
+#endif // cpPlugins_SYS_WINDOWS
+  if( f == NULL )
   {
-    dlclose( hnd );
+    Self::_DLClose( hnd );
     throw std::runtime_error(
-      std::string(
-        "cpPlugins::Interface: Library not recognized as a cpPlugins library: "
-        ) + std::string( err )
+      "cpPlugins::Interface: Library not recognized as a cpPlugins library: "
       );
 
   } // fi
-  filters = f( );
-#endif // cpPlugins_SYS_WINDOWS
+  std::string descriptors = f( );
+
+  // Demangle descriptors
+  TFilters filters;
+  std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
+  std::istringstream str( descriptors );
+  while( str )
+  {
+    std::string value, category, name;
+    str >> value;
+    if( value == "" )
+      continue;
+    std::replace( value.begin( ), value.end( ), ':', ' ' );
+    std::istringstream value_str( value );
+    value_str >> category >> name;
+    filters[ category ].insert( name );
+
+  } // elihw
   return( filters );
 }
 
@@ -169,16 +286,16 @@ _DLGetCreator(
   TCreator c = NULL;
   std::string func_name = category + "_" + name;
 #ifdef cpPlugins_SYS_WINDOWS
-  // TODO:
+  c = ( TCreator )( ::GetProcAddress( ( HMODULE )hnd, func_name.c_str( ) ) );
 #else // cpPlugins_SYS_WINDOWS
-  c = ( TCreator )dlsym( hnd, func_name.c_str( ) );
+  c = ( TCreator )( dlsym( hnd, func_name.c_str( ) ) );
+#endif // cpPlugins_SYS_WINDOWS
   if( c == NULL )
     throw std::runtime_error(
       std::string( "cpPlugins::Interface: Class \"" ) +
       category + std::string( ":" ) + name +
       std::string( "\" does not have a valid creator function." )
       );
-#endif // cpPlugins_SYS_WINDOWS
   return( c );
 }
 
@@ -187,7 +304,7 @@ void cpPlugins::Interface::
 _DLClose( void* hnd )
 {
 #ifdef cpPlugins_SYS_WINDOWS
-  // TODO:
+  ::FreeLibrary( ( HMODULE )hnd );
 #else // cpPlugins_SYS_WINDOWS
   dlclose( hnd );
 #endif // cpPlugins_SYS_WINDOWS