cgma
|
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