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