source: trunk/src/core/library.cc @ 428

Last change on this file since 428 was 403, checked in by epyon, 10 years ago
  • got rid of exceptions
  • assert enhancements
  • lots of minor cleanup
File size: 4.0 KB
Line 
1// Copyright (C) 2012-2015 ChaosForge Ltd
2// http://chaosforge.org/
3//
4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
6
7#include "nv/core/library.hh"
8
9#if NV_PLATFORM == NV_WINDOWS
10#   define WIN32_LEAN_AND_MEAN
11#   include <windows.h>
12#   define NV_LIB_EXT ".dll"
13#   define NV_LIB_OPEN( name ) static_cast<void*>( LoadLibraryEx( name, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ) )
14#   define NV_LIB_GET( handle, name ) reinterpret_cast<void*>( GetProcAddress( static_cast<HMODULE>( handle ), name ) )
15#   define NV_LIB_CLOSE( handle ) ( FreeLibrary( static_cast<HMODULE>( handle ) ) != 0 )
16#elif NV_PLATFORM == NV_LINUX || NV_PLATFORM == NV_APPLE
17#   include <dlfcn.h>
18#   define NV_LIB_EXT ".so"
19#   define NV_LIB_OPEN( name ) dlopen( name, RTLD_LAZY | RTLD_GLOBAL)
20#   define NV_LIB_GET( handle, name ) dlsym( static_cast<void*>( handle ), name )
21#   define NV_LIB_CLOSE( handle ) ( dlclose( static_cast<void*>( handle ) ) == 0 )
22#elif NV_PLATFORM == NV_APPLE
23#   include "macUtils.h"
24#   include <dlfcn.h>
25#   define NV_LIB_EXT ".dylib"
26#   define NV_LIB_OPEN( name ) mac_loadExeBundle( name )
27#   define NV_LIB_GET( handle, name ) mac_getBundleSym( handle, name )
28#   define NV_LIB_CLOSE( handle ) ( mac_unloadExeBundle( handle ) == 0 )
29#endif
30
31#include "nv/core/logging.hh"
32
33using namespace nv;
34
35library::library()
36    : m_handle( nullptr ), m_name()
37{
38}
39
40void library::open( string_view name )
41{
42        m_name.assign( name.data(), name.size() );
43        if ( !open() )
44        {
45                m_handle = nullptr;
46                NV_LOG_CRITICAL( "library \"", name, "\" : failed to load!" );
47                NV_ABORT( "Can't load library!" );
48        }
49}
50
51bool nv::library::try_open( string_view name )
52{
53        m_name.assign( name.data(), name.size() );
54        if ( !open() )
55        {
56                m_handle = nullptr;
57                return false;
58        }
59        return true;
60}
61
62string_view library::get_name() const
63{
64    return string_view( m_name );
65}
66
67bool library::open( )
68{
69    if ( m_handle != NULL )
70    {
71        return true;
72    }
73    NV_LOG_NOTICE( "library \"", string_view( m_name ), "\" : loading..." );
74
75        std::string name = m_name;
76        string_view ext( NV_LIB_EXT );
77
78        if ( name.length() < ext.length() || name.substr( name.length() - ext.length(), ext.length() ) != ext )
79    {
80        name.append( ext.data(), ext.length() );
81    }
82
83    m_handle = NV_LIB_OPEN( name.c_str() );
84
85    if ( m_handle == NULL )
86    {
87                NV_LOG_NOTICE( "library \"", string_view( name ), "\" : failed to open!" );
88                return false;
89    }
90    NV_LOG_NOTICE( "library \"", string_view( name ), "\" : loaded." );
91        return true;
92}
93
94void* library::get( string_view symbol )
95{
96        void* result = NV_LIB_GET( m_handle, symbol.data() );
97    if ( !result )
98    {
99                NV_LOG_CRITICAL( "library \"", string_view( m_name ), "\" : can't find symbol \"", symbol, "\"" );
100                NV_ABORT( "Library symbol load failed!" );
101    }
102        return result;
103}
104
105void* nv::library::try_get( string_view symbol )
106{
107        return NV_LIB_GET( m_handle, symbol.data() );
108}
109
110bool library::is_open() const
111{
112        return m_handle != nullptr;
113}
114
115void library::close()
116{
117    if ( ! NV_LIB_CLOSE( m_handle ) )
118    {
119        NV_LOG_ERROR( "library \"", string_view( m_name ), "\" : can't close library!" );
120    }
121    m_handle = nullptr;
122}
123
124library::~library()
125{
126    if ( m_handle != nullptr )
127    {
128        close();
129    }
130}
131
132std::string library::get_error()
133{
134#if NV_PLATFORM == NV_WINDOWS
135    // We do hate WinAPI for code like this, don't we?
136    LPTSTR buffer = nullptr;
137    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
138        NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPTSTR>( &buffer ), 0, NULL );
139    std::string msg( reinterpret_cast<char*>( buffer ) );
140    LocalFree( buffer );
141    return msg;
142#elif NV_PLATFORM == NV_LINUX || NV_PLATFORM == NV_APPLE
143    return std::string( dlerror() );
144#else
145    return std::string("");
146#endif
147}
Note: See TracBrowser for help on using the repository browser.