]> Creatis software - cpPlugins.git/blobdiff - lib/cpPlugins/Interface.cxx
...
[cpPlugins.git] / lib / cpPlugins / Interface.cxx
index de6d63116e6c0b2b35bf58c1c4f9d0ba2bf72de5..259288243d5a309e803115bddb6e50a98645b210 100644 (file)
@@ -1,15 +1,11 @@
 #include <cpPlugins/Interface.h>
 
-#include <map>
-#include <set>
-#include <string>
-
 #ifdef cpPlugins_SYS_WINDOWS
+#  include <Windows.h>
 #else // cpPlugins_SYS_WINDOWS
 #  include <dlfcn.h>
 #endif // cpPlugins_SYS_WINDOWS
 
-
 // -------------------------------------------------------------------------
 cpPlugins::Interface::
 Interface( )
@@ -31,88 +27,118 @@ GetFilters( )
   return( this->m_Filters );
 }
 
+// -------------------------------------------------------------------------
+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( ... )
+    {
+      // Do nothing
+
+    } // yrt
+
+  } // elihw
+  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( );
+}
+
 // -------------------------------------------------------------------------
 void cpPlugins::Interface::
 LoadPluginFile( const std::string& filename )
 {
+  // Open library with its canonical path name
   auto canonical_fn = cpPlugins::PathHelper::CanonicalPath( filename );
-  void* hnd = NULL;
-  std::map< std::string, std::set< std::string > > filters;
-#ifdef cpPlugins_SYS_WINDOWS
-  // TODO:
-#else // cpPlugins_SYS_WINDOWS
-
-  // Try to load canonical filename and clean error messages
-  hnd = dlopen( canonical_fn.c_str( ), RTLD_NOW | RTLD_GLOBAL );
+  void* hnd = Self::_DLOpen( canonical_fn );
   if( hnd == NULL )
     throw std::runtime_error(
       std::string( "cpPlugins::Interface: Could not load library \"" ) +
       canonical_fn +
       std::string( "\"" )
       );
-  dlerror( );
 
-  // Init plugins
-  typedef const std::map< std::string, std::set< std::string > > ( *func_t )( );
-  auto func = ( func_t ) dlsym( hnd, "LoadedFilters" );
-  const char* func_error = dlerror( );
-  if( func_error != NULL )
-  {
-    dlclose( hnd );
-    throw std::runtime_error(
-      std::string( "cpPlugins::Interface: Library \"" ) +
-      canonical_fn +
-      std::string( "\" not recognized as a cpPlugins library." )
-      );
+  // Load filters
+  TFilters filters = Self::_DLGetFilters( hnd );
 
-  } // fi
-  filters = func( );
-#endif // cpPlugins_SYS_WINDOWS
-  if( hnd != NULL )
+  // Save the loaded filters info
+  bool save_handler = false;
+  for( auto catIt = filters.begin( ); catIt != filters.end( ); ++catIt )
   {
-    // Save the loaded filters names
-    for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt )
+    // Check if the filter is completely new
+    auto act_catIt = this->m_Filters.find( catIt->first );
+    for(
+      auto clsIt = catIt->second.begin( );
+      clsIt != catIt->second.end( );
+      ++clsIt
+      )
     {
-      auto colIt = this->m_Filters.find( cIt->first );
-      for( auto fIt = cIt->second.begin( ); fIt != cIt->second.end( ); ++fIt )
+      bool new_filter = true;
+      if( act_catIt != this->m_Filters.end( ) )
+        new_filter =
+          ( act_catIt->second.find( *clsIt ) == act_catIt->second.end( ) );
+
+      // Ok, it is new
+      if( new_filter )
       {
-        bool found = false;
-        if( colIt != this->m_Filters.end( ) )
+        // Update filters container
+        TCreator creator = Self::_DLGetCreator( hnd, catIt->first, *clsIt );
+        if( creator != NULL )
         {
-          auto rowIt = colIt->second.find( *fIt );
-          if( rowIt != colIt->second.end( ) )
-            found = true;
+          this->m_DynFilters[ catIt->first][ *clsIt ] =
+            TDynFunc( canonical_fn, creator );
+          this->m_Filters[ catIt->first ].insert( *clsIt );
+          save_handler = true;
 
         } // fi
-        if( !found )
-          this->m_Filters[ cIt->first ][ *fIt ] = canonical_fn;
 
-      } // rof
+      } // fi
 
     } // rof
 
-    // Save the hnd
-    this->m_Plugins[ canonical_fn ] = hnd;
-  }
+  } // rof
+
+  // Keep dynlib handler, if needed
+  if( save_handler )
+    this->m_DynLibraries[ canonical_fn ] = hnd;
   else
-    throw std::runtime_error(
-      "cpPlugins::Interface: Operative system not yet supported."
-      );
+    Self::_DLClose( hnd );
 }
 
 // -------------------------------------------------------------------------
 void cpPlugins::Interface::
 UnloadAll( )
 {
-  auto pIt = this->m_Plugins.begin( );
-  for( ; pIt != this->m_Plugins.end( ); ++pIt )
-  {
-#ifdef cpPlugins_SYS_WINDOWS
-#else // cpPlugins_SYS_WINDOWS
-    dlclose( pIt->second );
-#endif // cpPlugins_SYS_WINDOWS
-  } // rof
-  this->m_Plugins.clear( );
+  for(
+    auto d = this->m_DynLibraries.begin( );
+    d != this->m_DynLibraries.end( );
+    ++d
+    )
+    Self::_DLClose( d->second );
+  this->m_DynLibraries.clear( );
+  this->m_DynFilters.clear( );
   this->m_Filters.clear( );
 }
 
@@ -120,38 +146,95 @@ UnloadAll( )
 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
 Create( const std::string& category, const std::string& name )
 {
-  cpPlugins::ProcessObject::Pointer filter;
-  auto cIt = this->m_Filters.find( category );
-  if( cIt != this->m_Filters.end( ) )
+  cpPlugins::ProcessObject::Pointer filter = NULL;
+  auto catIt = this->m_DynFilters.find( category );
+  if( catIt != this->m_DynFilters.end( ) )
   {
-    auto nIt = cIt->second.find( name );
-    if( nIt != cIt->second.end( ) )
-    {
-      auto pIt = this->m_Plugins.find( nIt->second );
-      if( pIt != this->m_Plugins.end( ) )
-      {
+    auto clsIt = catIt->second.find( name );
+    if( clsIt != catIt->second.end( ) )
+      filter = clsIt->second.second( );
+
+  } // fi
+  return( filter );
+}
+
+// -------------------------------------------------------------------------
+void* cpPlugins::Interface::
+_DLOpen( const std::string& fname )
+{
+  void* hnd = NULL;
 #ifdef cpPlugins_SYS_WINDOWS
+  hnd = ::LoadLibraryA( fname.c_str( ) );
 #else // cpPlugins_SYS_WINDOWS
-        std::string func_name = category + "_" + name;
-        typedef cpPlugins::ProcessObject::Pointer ( *func_t )( );
-        auto func = ( func_t ) dlsym( pIt->second, func_name.c_str( ) );
-        if( func == NULL )
-        {
-          throw std::runtime_error(
-            std::string( "cpPlugins::Interface: Class \"" ) +
-            category + std::string( ":" ) + name +
-            std::string( "\" does not have a valid creator function." )
-            );
-
-        } // fi
-        filter = func( );
+  hnd = dlopen( fname.c_str( ), RTLD_NOW | RTLD_GLOBAL );
+  dlerror( );
 #endif // cpPlugins_SYS_WINDOWS
-      } // fi
+  return( hnd );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Interface::
+TFilters cpPlugins::Interface::
+_DLGetFilters( void* hnd )
+{
+  typedef const TFilters ( *f_t )( );
 
-    } // fi
+  TFilters filters;
+#ifdef cpPlugins_SYS_WINDOWS
+  auto f = ( f_t )(
+    ::GetProcAddress( ( HMODULE )hnd, "cpPlugins_LoadedFilters" )
+    );
+  std::cout << f << std::endl;
+#else // cpPlugins_SYS_WINDOWS
+  auto f = ( f_t ) dlsym( hnd, "cpPlugins_LoadedFilters" );
+  const char* err = dlerror( );
+  if( err != NULL )
+  {
+    dlclose( hnd );
+    throw std::runtime_error(
+      std::string(
+        "cpPlugins::Interface: Library not recognized as a cpPlugins library: "
+        ) + std::string( err )
+      );
 
   } // fi
-  return( filter );
+#endif // cpPlugins_SYS_WINDOWS
+  filters = f( );
+  return( filters );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Interface::
+TCreator cpPlugins::Interface::
+_DLGetCreator(
+  void* hnd, const std::string& category, const std::string& name
+  )
+{
+  TCreator c = NULL;
+  std::string func_name = category + "_" + name;
+#ifdef cpPlugins_SYS_WINDOWS
+  // TODO:
+#else // cpPlugins_SYS_WINDOWS
+  c = ( TCreator )dlsym( hnd, func_name.c_str( ) );
+  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 );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::
+_DLClose( void* hnd )
+{
+#ifdef cpPlugins_SYS_WINDOWS
+  ::FreeLibrary( ( HMODULE )hnd );
+#else // cpPlugins_SYS_WINDOWS
+  dlclose( hnd );
+#endif // cpPlugins_SYS_WINDOWS
 }
 
 // eof - $RCSfile$