/** * @brief Open library * @param libName - [in] library file name * @return true - loaded successfully, false otherwise */ bool DynamicLibrary::Open( const PDL_CHAR * libName, bool resolveSymbols ) { if ( !libName ) { return false; } library_ = #if PLATFORM_WIN32 ::LoadLibraryExA( libName, NULL, ( resolveSymbols ) ? 0 : DONT_RESOLVE_DLL_REFERENCES ); #elif PLATFORM_POSIX dlopen( libName, RTLD_GLOBAL | ( ( resolveSymbols ) ? RTLD_NOW : RTLD_LAZY ) ); #endif if ( library_ ) { libraryName_ = libName; } else { const pdl_string nameWithExt( pdl_string( libName ) + pdl_string( GetDefaultExt() ) ); library_ = #if PLATFORM_WIN32 ::LoadLibraryExA( nameWithExt.c_str(), NULL, ( resolveSymbols ) ? 0 : DONT_RESOLVE_DLL_REFERENCES ); #elif PLATFORM_POSIX dlopen( nameWithExt.c_str(), RTLD_GLOBAL | ( ( resolveSymbols ) ? RTLD_NOW : RTLD_LAZY ) ); #endif if ( library_ ) { libraryName_ = libName; } } return ( library_ ); }
/** * @brief Get dynamic library * @param libName - [in] library file name * @return dynamic library * @throw LoaderException - cannot load library */ DynamicLibrary & DynamicLibraryManager::GetLibrary( const PDL_CHAR * libName ) { DynamicLibrary & library = GetLibraryInstance( libName ); if ( !library.Opened() ) { // We tried to load this library before, but we've failed throw LoaderException( pdl_string( "Cannot load library `" ) + pdl_string( libName ) + pdl_string( "`" ) ); } return library; }
/** * @brief Get last error description * @return last error description */ pdl_string DynamicLibrary::GetLastError() const { try { #if PLATFORM_WIN32 LPSTR lpMsgBuf = NULL; const DWORD res = ::FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, ::GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast< LPSTR >( &lpMsgBuf ), 0, NULL ); pdl_string errorText; if ( res != 0 ) { errorText.assign( lpMsgBuf ); ( void ) ::LocalFree( lpMsgBuf ); } #elif PLATFORM_POSIX const pdl_string errorText( dlerror() ); #endif return errorText; } catch ( ... ) { return pdl_string(); } }
/** * @brief Get symbol by name * @param symbolName - [in] symbol name * @return pointer to symbol, 0 if not found */ void * DynamicLibrary::GetSymbolByName( const PDL_CHAR * symbolName ) { if ( !library_ ) { throw LoaderException( pdl_string( "Library is not opened" ) ); } return #if PLATFORM_WIN32 static_cast< void * >( ::GetProcAddress( library_, symbolName ) ); #elif PLATFORM_POSIX dlsym( library_, symbolName ); #endif }
/** * @brief Get class instance * @param className - [in] class name * @return pointer to class instance */ DynamicClass * DynamicLibrary::GetInstance( const PDL_CHAR * className ) { const InstanceMap::iterator loadedInstance( instances_.find( className ) ); if ( loadedInstance != instances_.end() ) { return ( loadedInstance -> second ); } const pdl_string builderName( pdl_string( "Create" ) + pdl_string( className ) ); // Tricky code to prevent compiler error // ISO C++ forbids casting between pointer-to-function and pointer-to-object DynamicBuilder builder = 0; void * symbol = GetSymbolByName( builderName.c_str() ); ( void ) memcpy( &builder, &symbol, sizeof( void * ) ); if ( !builder ) { instances_[ className ] = 0; throw LoaderException( pdl_string( "Class `" ) + pdl_string( className ) + pdl_string( "` not found in " ) + libraryName_ ); } DynamicClass * instance = ( DynamicClass * )( *builder )(); instances_[ className ] = instance; return instance; }
/** * @brief Get dynamic library instance * @param libName - [in] library file name * @return dynamic library instance */ DynamicLibrary & DynamicLibraryManager::GetLibraryInstance( const PDL_CHAR * libName ) { if ( !libName ) { throw LoaderException( pdl_string( "Library name is 0" ) ); } DynamicLibrary * library = 0; const LibraryMap::iterator libraryInstance( libraries_.find( libName ) ); if ( libraryInstance != libraries_.end() ) { library = libraryInstance -> second; } else { library = new DynamicLibrary(); libraries_[ libName ] = library; if ( ( library ) && ( !library -> Open( libName, true ) ) ) { // This is the first time we try to load this library. // We are able to specify the reason of failure. throw LoaderException( pdl_string( "Cannot load library `" ) + pdl_string( libName ) + pdl_string( "`: " ) + library -> GetLastError() ); } } if ( !library ) { // Actually, this should never happen. // If it has happened, this means serious memory damage throw LoaderException( pdl_string( "Internal error" ) ); } return ( *library ); }