// Copyright (C) 2012 Kornel Kisielewicz // This file is part of NV Libraries. // For conditions of distribution and use, see copyright notice in nv.hh #include "nv/common.hh" #include "nv/library.hh" #include #if NV_PLATFORM == NV_WINDOWS # define WIN32_LEAN_AND_MEAN # include # define NV_LIB_EXT ".dll" # define NV_LIB_HANDLE HMODULE # define NV_LIB_OPEN( name ) LoadLibraryEx( name, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ) # define NV_LIB_GET( handle, name ) GetProcAddress( handle, name ) # define NV_LIB_CLOSE( name ) !FreeLibrary( name ) #elif NV_PLATFORM == NV_LINUX # include # define NV_LIB_EXT ".so" # define NV_LIB_HANDLE void* # define NV_LIB_OPEN( name ) dlopen( name, RTLD_LAZY | RTLD_GLOBAL) # define NV_LIB_GET( handle, name ) dlsym( handle, name ) # define NV_LIB_CLOSE( name ) dlclose( name ) #elif NV_PLATFORM == NV_APPLE # include "macUtils.h" # include # define NV_LIB_EXT ".dylib" # define NV_LIB_HANDLE CFBundleRef # define NV_LIB_OPEN( name ) mac_loadExeBundle( name ) # define NV_LIB_GET( handle, name ) mac_getBundleSym( handle, name ) # define NV_LIB_CLOSE( name ) mac_unloadExeBundle( name ) #endif #include "nv/logging.hh" using namespace nv; library::library( const std::string& name ) : m_name( name ) { m_handle = NULL; open(); } void library::open( const std::string& name ) { m_name = name; open(); } const std::string& library::get_name() const { return m_name; } void library::open() { if ( m_handle != NULL ) { return; } NV_LOG( LOG_NOTICE, "library : loading '" + m_name + "'..." ); std::string name = m_name; std::string ext = NV_LIB_EXT; size_t ext_len = ext.length(); if ( name.length() < ext_len || name.substr( name.length() - ext_len, ext_len ) != ext ) { name += ext; } m_handle = (void*)NV_LIB_OPEN( name.c_str() ); if ( m_handle == NULL ) { NV_THROW( library_error, "Can't load library!", name ); } NV_LOG( LOG_NOTICE, "library : '" + name + "' loaded." ); } void* library::get( const std::string& symbol ) { void* result = (void*) NV_LIB_GET( (NV_LIB_HANDLE) m_handle, symbol.c_str() ); if ( !result ) { NV_THROW( library_error, "Can't find symbol " + symbol + "!", m_name ); } return result; } void library::close() { if ( NV_LIB_CLOSE( (NV_LIB_HANDLE)m_handle ) ) { NV_LOG( LOG_ERROR, "library : can't close library '" + m_name + "'!" ); } m_handle = NULL; NV_LOG( LOG_NOTICE, "library : '" + m_name + "' closed." ); } library::~library() { if ( m_handle != NULL ) { close(); } } std::string library::get_error() { #if NV_PLATFORM == NV_WINDOWS // We do hate WinAPI for code like this, don't we? LPVOID buffer; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &buffer, 0, NULL ); std::string msg( (char*)buffer ); LocalFree( buffer ); return msg; #elif NV_PLATFORM == NV_LINUX || NV_PLATFORM == NV_APPLE return std::string(dlerror()); #else return std::string(""); #endif }