From 3d5417d682ae768bf6393f1b0d1f6b1a1755e0bd Mon Sep 17 00:00:00 2001 From: Leonardo Florez-Valencia Date: Wed, 9 Mar 2016 19:04:19 -0500 Subject: [PATCH] ... --- appli/PipelineEditor/PipelineEditor.cxx | 56 ++++- appli/PipelineEditor/PipelineEditor.h | 42 +++- appli/PipelineEditor/main.cxx | 3 +- appli/bash/cpPlugins_HostCreator.cxx | 17 +- appli/examples/CMakeLists.txt | 1 + .../examples/example_LoadPluginsDirectory.cxx | 41 ++++ appli/examples/example_LoadPluginsFile.cxx | 7 +- appli/examples/example_ReadWriteImage.cxx | 2 +- .../example_ReadWriteImageWithWorkspace.cxx | 2 +- cmake/CMakeLists.txt | 16 ++ cmake/cpPluginsConfig.cmake.in | 112 ++++++++++ lib/ItkVtkGlue/itkImageToVTKImageFilter.h | 4 +- lib/ItkVtkGlue/itkVTKImageToImageFilter.h | 4 +- lib/cpExtensions/QT/SimpleMPRWidget.cxx | 3 +- lib/cpPlugins/Image.h | 13 +- lib/cpPlugins/Interface.cxx | 203 +++++++++++------- lib/cpPlugins/Interface.h | 24 ++- plugins/cpPluginsIO/ImageWriter.cxx | 2 +- 18 files changed, 422 insertions(+), 130 deletions(-) create mode 100644 appli/examples/example_LoadPluginsDirectory.cxx create mode 100644 cmake/cpPluginsConfig.cmake.in diff --git a/appli/PipelineEditor/PipelineEditor.cxx b/appli/PipelineEditor/PipelineEditor.cxx index 139ae71..fcd3f42 100644 --- a/appli/PipelineEditor/PipelineEditor.cxx +++ b/appli/PipelineEditor/PipelineEditor.cxx @@ -25,11 +25,33 @@ this, SLOT( _Button##BUTTON( ) ) \ ) +// ------------------------------------------------------------------------- +bool PipelineEditor_Blocker:: +eventFilter( QObject* obj, QEvent* event ) +{ + return( true ); // -> Block all events + /* NOTE: correct implementation: + switch( event->type( ) ) + { + //list event you want to prevent here ... + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonDblClick: + //... + return( true ); + } // hctiws + return( this->QObject::eventFilter( obj, event ) ); + */ +} + // ------------------------------------------------------------------------- PipelineEditor:: -PipelineEditor( int argc, char* argv[], QWidget* parent ) +PipelineEditor( int argc, char* argv[], QApplication* app, QWidget* parent ) : QMainWindow( parent ), m_UI( new Ui::PipelineEditor ), + m_Application( app ), m_Workspace( NULL ), m_PluginsPath( "." ) { @@ -91,7 +113,8 @@ PipelineEditor:: { if( this->m_Workspace != NULL ) delete this->m_Workspace; - delete this->m_UI; + // TODO: this causes a segfault (?) + // delete this->m_UI; } // ------------------------------------------------------------------------- @@ -123,6 +146,7 @@ _LoadPluginsFromPath( const std::string& path ) void PipelineEditor:: _UpdateLoadedPlugins( ) { + this->_Block( ); auto filters = this->m_Interface.GetFilters( ); if( filters.size( ) == 0 ) { @@ -159,7 +183,7 @@ _UpdateLoadedPlugins( ) { QList< QTreeWidgetItem* > filter_items = this->m_UI->LoadedPlugins->findItems( - fIt->first.c_str( ), Qt::MatchExactly | Qt::MatchRecursive + fIt->c_str( ), Qt::MatchExactly | Qt::MatchRecursive ); auto fiIt = filter_items.begin( ); auto found_fiIt = filter_items.end( ); @@ -170,12 +194,30 @@ _UpdateLoadedPlugins( ) // Add filter if( found_fiIt == filter_items.end( ) ) QTreeWidgetItem* filter = new QTreeWidgetItem( - cat, QStringList( fIt->first.c_str( ) ) + cat, QStringList( fIt->c_str( ) ) ); } // rof } // rof + this->_UnBlock( ); +} + +// ------------------------------------------------------------------------- +void PipelineEditor:: +_Block( ) +{ + this->m_Application->setOverrideCursor( Qt::WaitCursor ); + this->m_Application->installEventFilter( &( this->m_Blocker ) ); +} + +// ------------------------------------------------------------------------- +void PipelineEditor:: +_UnBlock( ) +{ + while( this->m_Application->overrideCursor( ) ) + this->m_Application->restoreOverrideCursor( ); + this->m_Application->removeEventFilter( &( this->m_Blocker ) ); } // ------------------------------------------------------------------------- @@ -258,8 +300,8 @@ _ActionOpenWorkspace( ) dlg.setDefaultSuffix( QFileDialog::tr( "wxml" ) ); if( !( dlg.exec( ) ) ) return; - std::string fname = dlg.selectedFiles( ).at( 0 ).toStdString( ); + std::string fname = dlg.selectedFiles( ).at( 0 ).toStdString( ); if( this->m_Workspace != NULL ) delete this->m_Workspace; this->m_Workspace = new cpPlugins::Workspace( ); @@ -316,7 +358,9 @@ _ExecFilter( const std::string& filter_name ) if( this->m_Workspace != NULL ) { // Update filter, if needed + this->_Block( ); std::string err = this->m_Workspace->Execute( filter_name ); + this->_UnBlock( ); if( err != "" ) QMessageBox::critical( this, @@ -356,7 +400,9 @@ _ShowFilterOutput( this->m_UI->Viewer->SetDataColor( data_name, 1, 0, 0 ); else this->m_UI->Viewer->SetMainImage( data_name ); + this->_Block( ); this->m_UI->Viewer->ShowData( data_name ); + this->_UnBlock( ); } // fi } diff --git a/appli/PipelineEditor/PipelineEditor.h b/appli/PipelineEditor/PipelineEditor.h index ffeeafd..81a6d3d 100644 --- a/appli/PipelineEditor/PipelineEditor.h +++ b/appli/PipelineEditor/PipelineEditor.h @@ -2,10 +2,35 @@ #define __PIPELINEEDITOR__H__ // Qt stuff +#include #include #include #include +/** + */ +class PipelineEditor_Blocker + : public QObject +{ +protected: + virtual bool eventFilter( QObject* obj, QEvent* event ) override; +}; + +/* + class PipelineEditor; + struct PipelineEditor_Application + { + QApplication Application; + PipelineEditor Window; + PipelineEditor_Blocker Blocker; + PipelineEditor_Application( int argc, char* argv[] ); + void Show( ); + int Exec( ); + void Block( ); + void UnBlock( ); + }; +*/ + // ------------------------------------------------------------------------- namespace Ui { @@ -21,18 +46,21 @@ class PipelineEditor public: typedef PipelineEditor Self; - typedef QMainWindow Superclass; + typedef QMainWindow Superclass; public: explicit PipelineEditor( int argc, char* argv[], - QWidget* parent = 0 + QApplication* app, + QWidget* parent = NULL ); virtual ~PipelineEditor( ); protected: void _LoadPluginsFromPath( const std::string& path ); void _UpdateLoadedPlugins( ); + void _Block( ); + void _UnBlock( ); protected slots: void _ButtonLoadPluginsFile( ); @@ -45,10 +73,12 @@ protected slots: ); private: - Ui::PipelineEditor* m_UI; - cpPlugins::Workspace* m_Workspace; - cpPlugins::Interface m_Interface; - std::string m_PluginsPath; + Ui::PipelineEditor* m_UI; + QApplication* m_Application; + PipelineEditor_Blocker m_Blocker; + cpPlugins::Workspace* m_Workspace; + cpPlugins::Interface m_Interface; + std::string m_PluginsPath; }; #endif // __CPPIPELINEEDITOR__H__ diff --git a/appli/PipelineEditor/main.cxx b/appli/PipelineEditor/main.cxx index 2013a69..0914ece 100644 --- a/appli/PipelineEditor/main.cxx +++ b/appli/PipelineEditor/main.cxx @@ -6,9 +6,8 @@ int main( int argc, char* argv[] ) { QApplication a( argc, argv ); - PipelineEditor w( argc, argv, NULL ); + PipelineEditor w( argc, argv, &a ); w.show( ); - return( a.exec( ) ); } diff --git a/appli/bash/cpPlugins_HostCreator.cxx b/appli/bash/cpPlugins_HostCreator.cxx index 6721271..ee11adf 100644 --- a/appli/bash/cpPlugins_HostCreator.cxx +++ b/appli/bash/cpPlugins_HostCreator.cxx @@ -117,25 +117,14 @@ int main( int argc, char* argv[] ) // Write access function out_stream << "extern \"C\" std::map< std::string, std::set< std::string > > " - << "LoadedFilters( )" << std::endl << "{" << std::endl + << "cpPlugins_LoadedFilters( )" << std::endl << "{" << std::endl << " std::map< std::string, std::set< std::string > > classes;" << std::endl; - int i = 0; for( auto iIt = info.begin( ); iIt != info.end( ); ++iIt ) - { for( auto jIt = iIt->second.begin( ); jIt != iIt->second.end( ); ++jIt ) - { out_stream - << " auto f" << i << " = " - << jIt->second << "::" << jIt->first - << "::New( );" << std::endl - << " classes[ f" << i << "->GetClassCategory( ) ].insert( " - << "f" << i << "->GetClassName( ) );" << std::endl; - i++; - - } // rof - - } // rof + << " classes[ \"" << iIt->first + << "\" ].insert( \"" << jIt->first << "\" );" << std::endl; out_stream << " return( classes );" << std::endl << "}" << std::endl << std::endl; diff --git a/appli/examples/CMakeLists.txt b/appli/examples/CMakeLists.txt index 020c854..752c62b 100644 --- a/appli/examples/CMakeLists.txt +++ b/appli/examples/CMakeLists.txt @@ -1,6 +1,7 @@ SET( examples_SOURCES example_LoadPluginsFile + example_LoadPluginsDirectory example_ReadWriteImage example_ReadWriteImageWithWorkspace ) diff --git a/appli/examples/example_LoadPluginsDirectory.cxx b/appli/examples/example_LoadPluginsDirectory.cxx new file mode 100644 index 0000000..cdda427 --- /dev/null +++ b/appli/examples/example_LoadPluginsDirectory.cxx @@ -0,0 +1,41 @@ +#include +#include + +int main( int argc, char* argv[] ) +{ + if( argc < 2 ) + { + std::cerr << "Usage: " << argv[ 0 ] << " plugins_libraries" << std::endl; + return( 1 ); + + } // fi + + // Load interface + cpPlugins::Interface interface; + for( int i = 1; i < argc; ++i ) + { + try + { + interface.LoadPluginFile( argv[ i ] ); + } + catch( ... ) + { + } // yrt + + } // rof + + // Show loaded filters + auto filters = interface.GetFilters( ); + for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt ) + { + std::cout << "Category: " << cIt->first << std::endl; + for( auto nIt = cIt->second.begin( ); nIt != cIt->second.end( ); ++nIt ) + std::cout + << "\tFilter: " << *nIt + << std::endl; + + } // rof + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/example_LoadPluginsFile.cxx b/appli/examples/example_LoadPluginsFile.cxx index e43f383..ddef170 100644 --- a/appli/examples/example_LoadPluginsFile.cxx +++ b/appli/examples/example_LoadPluginsFile.cxx @@ -19,12 +19,12 @@ int main( int argc, char* argv[] ) catch( std::exception& err ) { std::cerr - << "Interface load failed on \"" << argv[ 1 ] << "\": " + << "Error caught:" << err.what( ) << std::endl; return( 1 ); - } // fi + } // yrt // Show loaded filters auto filters = interface.GetFilters( ); @@ -33,8 +33,7 @@ int main( int argc, char* argv[] ) std::cout << "Category: " << cIt->first << std::endl; for( auto nIt = cIt->second.begin( ); nIt != cIt->second.end( ); ++nIt ) std::cout - << "\tFilter: " << nIt->first - << " (" << nIt->second << ")" + << "\tFilter: " << *nIt << std::endl; } // rof diff --git a/appli/examples/example_ReadWriteImage.cxx b/appli/examples/example_ReadWriteImage.cxx index 50b8f43..3eb89d8 100644 --- a/appli/examples/example_ReadWriteImage.cxx +++ b/appli/examples/example_ReadWriteImage.cxx @@ -72,7 +72,7 @@ int main( int argc, char* argv[] ) for( int i = 2; i < argc - 1; ++i ) reader_params->AddToOpenFileNameList( "FileNames", argv[ i ] ); auto writer_params = writer->GetParameters( ); - writer_params->SetOpenFileName( "FileName", argv[ argc - 1 ] ); + writer_params->SetSaveFileName( "FileName", argv[ argc - 1 ] ); // Connect filters writer->SetInput( "Input", reader->GetOutput( "Output" ) ); diff --git a/appli/examples/example_ReadWriteImageWithWorkspace.cxx b/appli/examples/example_ReadWriteImageWithWorkspace.cxx index 9a82138..630744a 100644 --- a/appli/examples/example_ReadWriteImageWithWorkspace.cxx +++ b/appli/examples/example_ReadWriteImageWithWorkspace.cxx @@ -42,7 +42,7 @@ int main( int argc, char* argv[] ) for( int i = 2; i < argc - 1; ++i ) reader_params->AddToOpenFileNameList( "FileNames", argv[ i ] ); auto writer_params = writer->GetParameters( ); - writer_params->SetOpenFileName( "FileName", argv[ argc - 1 ] ); + writer_params->SetSaveFileName( "FileName", argv[ argc - 1 ] ); // Execute std::string err = workspace.Execute( ); diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 4b26944..7db97e9 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -1 +1,17 @@ +CONFIGURE_FILE( + cpPluginsConfig.cmake.in + ${PROJECT_BINARY_DIR}/cpPluginsConfig.cmake + @ONLY + ) + +## ======================== +## -- Installation rules -- +## ======================== + +INSTALL( + FILES + ${PROJECT_BINARY_DIR}/cpPluginsConfig.cmake + DESTINATION share/cmake + ) + ## eof - $RCSfile$ diff --git a/cmake/cpPluginsConfig.cmake.in b/cmake/cpPluginsConfig.cmake.in new file mode 100644 index 0000000..734e990 --- /dev/null +++ b/cmake/cpPluginsConfig.cmake.in @@ -0,0 +1,112 @@ +# =================================== +# -- Some configurations variables -- +# =================================== + +SET(USE_QT4 "@QT4_FOUND@") + +# ======================= +# -- Find dependencies -- +# ======================= + +# Find ITK and VTK +SET(ITK_DIR @ITK_DIR@) +FIND_PACKAGE(ITK REQUIRED) +INCLUDE(${ITK_USE_FILE}) + +SET(VTK_DIR @VTK_DIR@) +FIND_PACKAGE(VTK REQUIRED) +INCLUDE(${VTK_USE_FILE}) + +# Do not use itk-vtk glue --> problems ahead!!! +IF(ITKVtkGlue_LOADED) + MESSAGE(FATAL_ERROR "ITKVtkGlue module is available. Please re-compile your ITK without it. It could lead to nasty compilation problems... Just waiting for Kitware to solve it.") +ENDIF(ITKVtkGlue_LOADED) + +IF(USE_QT4 EQUAL "1") + SET(QT_QMAKE_EXECUTABLE @QT_QMAKE_EXECUTABLE@) + FIND_PACKAGE(Qt4 REQUIRED) + INCLUDE(${QT_USE_FILE}) + + ## Check for required vtk-qt4 modules + SET( + vtk_required_modules + vtkGUISupportQt + vtkGUISupportQtOpenGL + ) + FOREACH(vtk_module ${vtk_required_modules}) + IF(NOT ${vtk_module}_LOADED) + MESSAGE( + FATAL_ERROR + "${vtk_module} module is required but not available." + ) + ENDIF(NOT ${vtk_module}_LOADED) + ENDFOREACH(vtk_module) +ENDIF(USE_QT4 EQUAL "1") + + +# ========================= +# -- Include directories -- +# ========================= + +INCLUDE_DIRECTORIES( + @PROJECT_SOURCE_DIR@/lib + @PROJECT_SOURCE_DIR@/lib/third_party + @PROJECT_SOURCE_DIR@/lib/ItkVtkGlue + @PROJECT_BINARY_DIR@/lib + @PROJECT_BINARY_DIR@/lib/third_party + @PROJECT_BINARY_DIR@/lib/ItkVtkGlue + @CMAKE_INSTALL_PREFIX@/include + @CMAKE_INSTALL_PREFIX@/include/third_party + @CMAKE_INSTALL_PREFIX@/include/ItkVtkGlue + ) + +# ========================= +# -- Library directories -- +# ========================= + +IF(MSVC) + LINK_DIRECTORIES( + @PROJECT_BINARY_DIR@/$(ConfigurationName) + @CMAKE_INSTALL_PREFIX@/bin + @CMAKE_INSTALL_PREFIX@/lib + ) +ELSE(MSVC) + LINK_DIRECTORIES( + @PROJECT_BINARY_DIR@ + @CMAKE_INSTALL_PREFIX@/bin + @CMAKE_INSTALL_PREFIX@/lib + ) +ENDIF(MSVC) + +# =================== +# -- Library names -- +# =================== + +SET(cpExtensions_LIBRARY cpExtensions) +SET(cpPlugins_LIBRARY cpPlugins) + +# ====================== +# -- Executable names -- +# ====================== + +IF(MSVC) + FIND_PROGRAM( + cpPlugins_HostCreator_APP + NAMES cpPlugins_HostCreator + HINTS /usr /usr/local + PATHS @CMAKE_INSTALL_PREFIX@/bin @PROJECT_BINARY_DIR@/Debug @PROJECT_BINARY_DIR@/Release @PROJECT_BINARY_DIR@/MinSizeRel @PROJECT_BINARY_DIR@/RelWithDebInfo + PATH_SUFFIXES bin sbin + DOC "Where is cpPlugins_HostCreator?" + ) +ELSE(MSVC) + FIND_PROGRAM( + cpPlugins_HostCreator_APP + NAMES cpPlugins_HostCreator + HINTS /usr /usr/local + PATHS @CMAKE_INSTALL_PREFIX@/bin @PROJECT_BINARY_DIR@ + PATH_SUFFIXES bin sbin + DOC "Where is cpPlugins_HostCreator?" + ) +ENDIF(MSVC) + +## eof - $RCSfile$ diff --git a/lib/ItkVtkGlue/itkImageToVTKImageFilter.h b/lib/ItkVtkGlue/itkImageToVTKImageFilter.h index 9390eb8..0fc27ac 100644 --- a/lib/ItkVtkGlue/itkImageToVTKImageFilter.h +++ b/lib/ItkVtkGlue/itkImageToVTKImageFilter.h @@ -95,8 +95,8 @@ protected: virtual ~ImageToVTKImageFilter(); private: - ImageToVTKImageFilter(const Self&) ITK_DELETE_FUNCTION; - void operator=(const Self&) ITK_DELETE_FUNCTION; + ImageToVTKImageFilter(const Self&) = delete; + void operator=(const Self&) = delete; ExporterFilterPointer m_Exporter; vtkImageImport * m_Importer; diff --git a/lib/ItkVtkGlue/itkVTKImageToImageFilter.h b/lib/ItkVtkGlue/itkVTKImageToImageFilter.h index b4427c8..2bb90d4 100644 --- a/lib/ItkVtkGlue/itkVTKImageToImageFilter.h +++ b/lib/ItkVtkGlue/itkVTKImageToImageFilter.h @@ -83,8 +83,8 @@ protected: virtual ~VTKImageToImageFilter(); private: - VTKImageToImageFilter(const Self&) ITK_DELETE_FUNCTION; - void operator=(const Self&) ITK_DELETE_FUNCTION; + VTKImageToImageFilter(const Self&) = delete; + void operator=(const Self&) = delete; typedef vtkSmartPointer ImageExportPointer; ImageExportPointer m_Exporter; diff --git a/lib/cpExtensions/QT/SimpleMPRWidget.cxx b/lib/cpExtensions/QT/SimpleMPRWidget.cxx index 62b9296..fa0214c 100644 --- a/lib/cpExtensions/QT/SimpleMPRWidget.cxx +++ b/lib/cpExtensions/QT/SimpleMPRWidget.cxx @@ -58,7 +58,8 @@ SimpleMPRWidget( QWidget* parent ) cpExtensions::QT::SimpleMPRWidget:: ~SimpleMPRWidget( ) { - delete this->m_UI; + // TODO: this causes a segfault (?) + // delete this->m_UI; } // ------------------------------------------------------------------------- diff --git a/lib/cpPlugins/Image.h b/lib/cpPlugins/Image.h index fa7c7c3..2bdde70 100644 --- a/lib/cpPlugins/Image.h +++ b/lib/cpPlugins/Image.h @@ -13,20 +13,23 @@ namespace cpPlugins : public DataObject { public: - typedef Image Self; - typedef DataObject Superclass; + typedef Image Self; + typedef DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; public: + itkNewMacro( Self ); + itkTypeMacro( Image, DataObject ); cpPlugins_Id_Macro( Image, Object ); public: - Image( ); - virtual ~Image( ); - virtual void SetITK( itk::LightObject* o ) override; virtual void SetVTK( vtkObjectBase* o ) override; protected: + Image( ); + virtual ~Image( ); template< unsigned int D > inline bool _ITK_2_VTK_0( itk::LightObject* o ); diff --git a/lib/cpPlugins/Interface.cxx b/lib/cpPlugins/Interface.cxx index de6d631..0ee1faf 100644 --- a/lib/cpPlugins/Interface.cxx +++ b/lib/cpPlugins/Interface.cxx @@ -1,15 +1,10 @@ #include -#include -#include -#include - #ifdef cpPlugins_SYS_WINDOWS #else // cpPlugins_SYS_WINDOWS # include #endif // cpPlugins_SYS_WINDOWS - // ------------------------------------------------------------------------- cpPlugins::Interface:: Interface( ) @@ -35,84 +30,75 @@ GetFilters( ) 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 +106,91 @@ 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 + // TODO: #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 ); +} - } // fi +// ------------------------------------------------------------------------- +cpPlugins::Interface:: +TFilters cpPlugins::Interface:: +_DLGetFilters( void* hnd ) +{ + TFilters filters; +#ifdef cpPlugins_SYS_WINDOWS + // TODO: +#else // cpPlugins_SYS_WINDOWS + typedef const TFilters ( *f_t )( ); + 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 ); + filters = f( ); +#endif // cpPlugins_SYS_WINDOWS + 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 + // TODO: +#else // cpPlugins_SYS_WINDOWS + dlclose( hnd ); +#endif // cpPlugins_SYS_WINDOWS } // eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface.h b/lib/cpPlugins/Interface.h index 7c860db..61ddf3b 100644 --- a/lib/cpPlugins/Interface.h +++ b/lib/cpPlugins/Interface.h @@ -4,6 +4,7 @@ #include #include #include +#include #include namespace cpPlugins @@ -13,8 +14,14 @@ namespace cpPlugins class cpPlugins_EXPORT Interface { public: - typedef std::map< std::string, std::string > TStringRow; - typedef std::map< std::string, TStringRow > TFilters; + typedef Interface Self; + + typedef cpPlugins::ProcessObject::Pointer ( *TCreator )( ); + typedef std::pair< std::string, TCreator > TDynFunc; + typedef std::map< std::string, TDynFunc > TDynFilter; + typedef std::map< std::string, TDynFilter > TDynFilters; + typedef std::map< std::string, void* > TDynLibraries; + typedef std::map< std::string, std::set< std::string > > TFilters; public: Interface( ); @@ -30,8 +37,17 @@ namespace cpPlugins ); protected: - std::map< std::string, void* > m_Plugins; - TFilters m_Filters; + static void* _DLOpen( const std::string& fname ); + static TFilters _DLGetFilters( void* hnd ); + static TCreator _DLGetCreator( + void* hnd, const std::string& category, const std::string& name + ); + static void _DLClose( void* hnd ); + + protected: + TDynLibraries m_DynLibraries; + TDynFilters m_DynFilters; + TFilters m_Filters; }; } // ecapseman diff --git a/plugins/cpPluginsIO/ImageWriter.cxx b/plugins/cpPluginsIO/ImageWriter.cxx index 4418c66..76be57c 100644 --- a/plugins/cpPluginsIO/ImageWriter.cxx +++ b/plugins/cpPluginsIO/ImageWriter.cxx @@ -66,7 +66,7 @@ _GD1( I* image ) if( image == NULL ) return( "IO::ImageWriter: Invalid pixel type." ); auto f = this->_CreateITK< itk::ImageFileWriter< I > >( ); - f->SetFileName( this->m_Parameters.GetOpenFileName( "FileName" ) ); + f->SetFileName( this->m_Parameters.GetSaveFileName( "FileName" ) ); f->SetInput( image ); f->Update( ); return( "" ); -- 2.45.1