cgma
CGMEngineDynamicLoader.cpp
Go to the documentation of this file.
00001 
00002 
00003 #include "CGMEngineDynamicLoader.hpp"
00004 
00005 #include "CubitMessage.hpp"
00006 #include <string.h>
00007 
00008 extern "C"
00009 {
00010   typedef GeometryQueryEngine* (*CGMEngineCreateQueryEngine)();
00011   typedef GeometryModifyEngine* (*CGMEngineCreateModifyEngine)();
00012 }
00013 
00014 // default engine library name is something like libCGM{engine_name}.so
00015 
00016 CGMEngineDynamicLoader::CGMEngineDynamicLoader(const CubitString& engine_name)
00017   : mEngineName(engine_name), 
00018     mEngineLibrary(CubitString("CGM") + engine_name),
00019     mLibraryHandle(CubitDynamicLoader::InvalidLibraryHandle),
00020     mLoadAttempted(CUBIT_FALSE),
00021     mQueryEngine(NULL),
00022     mModifyEngine(NULL)
00023 {
00024 }
00025 
00026 
00027 CGMEngineDynamicLoader::~CGMEngineDynamicLoader()
00028 {
00029   if(mLibraryHandle != CubitDynamicLoader::InvalidLibraryHandle)
00030   {
00031     unload_engine();
00032   }
00033 }
00034 
00035 CubitString CGMEngineDynamicLoader::get_engine_name()
00036 {
00037   return mEngineName;
00038 }
00039 
00040 CubitString CGMEngineDynamicLoader::get_library_base_name()
00041 {
00042   return mEngineLibrary;
00043 }
00044 
00045 void CGMEngineDynamicLoader::set_library_base_name(const CubitString& libname)
00046 {
00047   if(mLibraryHandle == CubitDynamicLoader::InvalidLibraryHandle)
00048   {
00049     mEngineLibrary = libname;
00050     mLoadAttempted = CUBIT_FALSE;
00051   }
00052 }
00053 
00054 CubitBoolean CGMEngineDynamicLoader::engine_exists()
00055 {
00056   if(mLibraryHandle != CubitDynamicLoader::InvalidLibraryHandle)
00057     return CUBIT_TRUE;
00058 
00059   // try for a debug version with _d on it first.
00060 #if defined(_WIN32) && defined(_DEBUG)
00061   CubitString debug_libname = CubitDynamicLoader::library_prefix() +
00062             mEngineLibrary +
00063             CubitString("_d") +
00064             CubitDynamicLoader::library_extension();
00065   if(CubitDynamicLoader::library_exists(debug_libname.c_str()))
00066     return CUBIT_TRUE;
00067 #endif
00068   
00069   CubitString libname = CubitDynamicLoader::library_prefix() +
00070             mEngineLibrary +
00071             CubitDynamicLoader::library_extension();
00072   if(CubitDynamicLoader::library_exists(libname.c_str()))
00073     return CUBIT_TRUE;
00074 
00075   return CUBIT_FALSE;
00076 }
00077 
00078 CubitStatus CGMEngineDynamicLoader::load_engine()
00079 {
00080   if(mLibraryHandle == CubitDynamicLoader::InvalidLibraryHandle)
00081   {
00082     // try for a debug version with _d on it first.
00083 #if defined(_WIN32) && defined(_DEBUG)
00084     CubitString debug_libname = CubitDynamicLoader::library_prefix() +
00085               mEngineLibrary +
00086               CubitString("_d") +
00087               CubitDynamicLoader::library_extension();
00088     mLibraryHandle = CubitDynamicLoader::load_library(debug_libname.c_str());
00089 #endif
00090 
00091     if(mLibraryHandle == CubitDynamicLoader::InvalidLibraryHandle)
00092     {
00093       CubitString libname = CubitDynamicLoader::library_prefix() +
00094                             mEngineLibrary +
00095                             CubitDynamicLoader::library_extension();
00096 
00097       mLibraryHandle = CubitDynamicLoader::load_library(libname.c_str());
00098     }
00099 
00100     mLoadAttempted = CUBIT_TRUE;
00101     if(mLibraryHandle == CubitDynamicLoader::InvalidLibraryHandle)
00102     {
00103       CubitString error = CubitDynamicLoader::get_error();
00104       if(error != CubitString())
00105       {
00106         PRINT_ERROR("%s\n", error.c_str());
00107       }
00108       return CUBIT_FAILURE;
00109     }
00110   }
00111   return CUBIT_SUCCESS;
00112 }
00113 
00114 CubitStatus CGMEngineDynamicLoader::unload_engine()
00115 { 
00116   return CUBIT_SUCCESS;
00117 
00118   /*
00119 
00120 //don't unload cubitcatia.dll
00121 #ifdef CATIA 
00122   if( mEngineName == "CATIA")
00123     return CUBIT_SUCCESS;
00124 #endif 
00125 
00126   if(mLibraryHandle != CubitDynamicLoader::InvalidLibraryHandle)
00127   {
00128     CubitDynamicLoader::unload_library(mLibraryHandle);
00129     mLoadAttempted = CUBIT_FALSE;
00130     mLibraryHandle = CubitDynamicLoader::InvalidLibraryHandle;
00131     mQueryEngine = NULL;
00132     mModifyEngine = NULL;
00133   } 
00134   return CUBIT_SUCCESS;
00135   */
00136 }
00137 
00138 
00139 extern "C" {
00140   typedef const char* (*FpVersion)();
00141 }
00142 
00143 CubitBoolean CGMEngineDynamicLoader::check_engine_version()
00144 {
00145   // library was already loaded, so just look up the version function
00146 
00147   CubitString symbol = CubitString("dynamic_") + mEngineName + CubitString("_get_cgm_version");
00148 
00149   // Note: this is a nasty hack to avoid the warning:
00150   // ISO C++ forbids casting between pointer-to-function and pointer-to-object
00151   // Even with reinterpret_cast, this warning is still generated
00152   // GCC accepts reinterpret_cast for purposes like in dlsym calls as an extension,
00153   // but that might not work for other compilers
00154   // This union-trick has been applied to some open source code, like:
00155   // https://mail.gnome.org/archives/commits-list/2011-February/msg06409.html
00156   // http://sourceforge.net/p/scstudio/mailman/message/29083334/
00157   union {
00158     void* ptr;
00159     FpVersion func;
00160   } cast_u;
00161   cast_u.ptr = CubitDynamicLoader::get_symbol_address(mLibraryHandle, symbol.c_str());
00162 
00163   FpVersion fp_version = cast_u.func;
00164 
00165   if(!fp_version)
00166   {
00167     PRINT_ERROR("Failed to load CGM %s engine : Can't find version\n", mEngineName.c_str());
00168     return CUBIT_FALSE;
00169   }
00170 
00171   // TODO -- use real versioning system
00172   if(strcmp((*fp_version)(), "1.0") != 0)
00173   {
00174     PRINT_ERROR("Failed to load CGM %s engine : wrong version number\n", mEngineName.c_str());
00175     return CUBIT_FALSE;
00176   }
00177 
00178   return TRUE;
00179 }
00180 
00181 GeometryQueryEngine* CGMEngineDynamicLoader::get_gqe()
00182 {
00183   if(mQueryEngine)
00184     return mQueryEngine;  
00185 
00186   if(mLoadAttempted == CUBIT_FALSE)
00187     load_engine();
00188 
00189   if(mLibraryHandle == CubitDynamicLoader::InvalidLibraryHandle)
00190   {
00191     PRINT_ERROR("Failed to load CGM %s engine\n", mEngineName.c_str());
00192     return NULL;
00193   }
00194 
00195   // check for incompatible CGM version
00196   if(check_engine_version() == CUBIT_FALSE)
00197     return NULL;
00198 
00199   CubitString symbol = CubitString("dynamic_") + mEngineName + CubitString("_create_gqe");
00200 
00201   // Note: this is a nasty hack to avoid the warning:
00202   // ISO C++ forbids casting between pointer-to-function and pointer-to-object
00203   // Even with reinterpret_cast, this warning is still generated
00204   // GCC accepts reinterpret_cast for purposes like in dlsym calls as an extension,
00205   // but that might not work for other compilers
00206   // This union-trick has been applied to some open source code, like:
00207   // https://mail.gnome.org/archives/commits-list/2011-February/msg06409.html
00208   // http://sourceforge.net/p/scstudio/mailman/message/29083334/
00209   union {
00210     void* ptr;
00211     CGMEngineCreateQueryEngine func;
00212   } cast_u;
00213   cast_u.ptr = CubitDynamicLoader::get_symbol_address(mLibraryHandle, symbol.c_str());
00214 
00215   CGMEngineCreateQueryEngine create_query_engine = cast_u.func;
00216 
00217   if(!create_query_engine)
00218   {
00219     PRINT_ERROR("Failed to get %s query engine\n", mEngineName.c_str());
00220     return NULL;
00221   }
00222 
00223   mQueryEngine = (*create_query_engine)();
00224 
00225   return mQueryEngine;
00226 }
00227 
00228     
00229 GeometryModifyEngine* CGMEngineDynamicLoader::get_gme()
00230 {
00231   if(mModifyEngine)
00232     return mModifyEngine;
00233 
00234   if(mLoadAttempted == CUBIT_FALSE)
00235     load_engine();
00236 
00237   if(mLibraryHandle == CubitDynamicLoader::InvalidLibraryHandle)
00238   {
00239     PRINT_ERROR("Failed to load CGM %s engine\n", mEngineName.c_str());
00240     return NULL;
00241   }
00242   
00243   // check for incompatible CGM version
00244   if(check_engine_version() == CUBIT_FALSE)
00245     return NULL;
00246   
00247   CubitString symbol = CubitString("dynamic_") + mEngineName + CubitString("_create_gme");
00248 
00249   // Note: this is a nasty hack to avoid the warning:
00250   // ISO C++ forbids casting between pointer-to-function and pointer-to-object
00251   // Even with reinterpret_cast, this warning is still generated
00252   // GCC accepts reinterpret_cast for purposes like in dlsym calls as an extension,
00253   // but that might not work for other compilers
00254   // This union-trick has been applied to some open source code, like:
00255   // https://mail.gnome.org/archives/commits-list/2011-February/msg06409.html
00256   // http://sourceforge.net/p/scstudio/mailman/message/29083334/
00257   union {
00258     void* ptr;
00259     CGMEngineCreateModifyEngine func;
00260   } cast_u;
00261   cast_u.ptr = CubitDynamicLoader::get_symbol_address(mLibraryHandle, symbol.c_str());
00262 
00263   CGMEngineCreateModifyEngine create_modify_engine = cast_u.func;
00264 
00265   if(!create_modify_engine)
00266   {
00267     PRINT_ERROR("Failed to get %s modify engine\n", mEngineName.c_str());
00268     return NULL;
00269   }
00270   
00271   mModifyEngine = (*create_modify_engine)();
00272 
00273   return mModifyEngine;
00274 }
00275 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines