source: trunk/src/library.cc @ 183

Last change on this file since 183 was 166, checked in by epyon, 12 years ago
  • library - try_open and try_get functions added for non-throwing access
  • lua - compatibility layer mode added - the whole system can bind to lua 5.1, 5.2 or LuaJIT as a *RUNTIME* choice
File size: 3.8 KB
Line 
1// Copyright (C) 2012 Kornel Kisielewicz
2// This file is part of NV Libraries.
3// For conditions of distribution and use, see copyright notice in nv.hh
4#include "nv/common.hh"
5#include "nv/library.hh"
6
7#include <string.h>
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_HANDLE HMODULE
14#   define NV_LIB_OPEN( name ) LoadLibraryEx( name, NULL, LOAD_WITH_ALTERED_SEARCH_PATH )
15#   define NV_LIB_GET( handle, name ) GetProcAddress( handle, name )
16#   define NV_LIB_CLOSE( name ) !FreeLibrary( name )
17#elif NV_PLATFORM == NV_LINUX || NV_PLATFORM == NV_APPLE
18#   include <dlfcn.h>
19#   define NV_LIB_EXT ".so"
20#   define NV_LIB_HANDLE void*
21#   define NV_LIB_OPEN( name ) dlopen( name, RTLD_LAZY | RTLD_GLOBAL)
22#   define NV_LIB_GET( handle, name ) dlsym( handle, name )
23#   define NV_LIB_CLOSE( name ) dlclose( name )
24#elif NV_PLATFORM == NV_APPLE
25#   include "macUtils.h"
26#   include <dlfcn.h>
27#   define NV_LIB_EXT ".dylib"
28#   define NV_LIB_HANDLE CFBundleRef
29#   define NV_LIB_OPEN( name ) mac_loadExeBundle( name )
30#   define NV_LIB_GET( handle, name ) mac_getBundleSym( handle, name )
31#   define NV_LIB_CLOSE( name ) mac_unloadExeBundle( name )
32#endif
33
34#include "nv/logging.hh"
35
36using namespace nv;
37
38library::library()
39    : m_handle( nullptr ), m_name()
40{
41}
42
43void library::open( const std::string& name )
44{
45        m_name = name;
46        if ( !open() )
47        {
48                m_handle = nullptr;
49                NV_THROW( library_error, "Can't load library!", name );
50        }
51}
52
53bool nv::library::try_open( const std::string& name )
54{
55        m_name = name;
56        if ( !open() )
57        {
58                m_handle = nullptr;
59                return false;
60        }
61        return true;
62}
63
64const std::string& library::get_name() const
65{
66    return m_name;
67}
68
69bool library::open( )
70{
71    if ( m_handle != NULL )
72    {
73        return true;
74    }
75    NV_LOG( LOG_NOTICE, "library : loading '" + m_name + "'..." );
76
77    std::string name = m_name;
78    std::string ext  = NV_LIB_EXT;
79    size_t ext_len   = ext.length();
80
81    if ( name.length() < ext_len || name.substr( name.length() - ext_len, ext_len ) != ext )
82    {
83        name += ext;
84    }
85
86    m_handle = (void*)NV_LIB_OPEN( name.c_str() );
87
88    if ( m_handle == NULL )
89    {
90                NV_LOG( LOG_NOTICE, "library : '" + name + "' failed to open." );
91                return false;
92    }
93    NV_LOG( LOG_NOTICE, "library : '" + name + "' loaded." );
94        return true;
95}
96
97void* library::get( const std::string& symbol )
98{
99        void* result = (void*) NV_LIB_GET( (NV_LIB_HANDLE) m_handle, symbol.c_str() );
100    if ( !result )
101    {
102        NV_THROW( library_error, "Can't find symbol " + symbol + "!", m_name );
103    }
104        return result;
105}
106
107void* nv::library::try_get( const std::string& symbol )
108{
109        return (void*) NV_LIB_GET( (NV_LIB_HANDLE) m_handle, symbol.c_str() );
110}
111
112bool library::is_open() const
113{
114        return m_handle != nullptr;
115}
116
117void library::close()
118{
119    if ( NV_LIB_CLOSE( (NV_LIB_HANDLE)m_handle ) )
120    {
121        NV_LOG( LOG_ERROR, "library : can't close library '" + m_name + "'!" );
122    }
123    m_handle = NULL;
124    NV_LOG( LOG_NOTICE, "library : '" + m_name + "' closed." );
125}
126
127library::~library()
128{
129    if ( m_handle != NULL )
130    {
131        close();
132    }
133}
134
135std::string library::get_error()
136{
137#if NV_PLATFORM == NV_WINDOWS
138    // We do hate WinAPI for code like this, don't we?
139    LPTSTR buffer = NULL;
140    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
141        NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &buffer, 0, NULL );
142    std::string msg( (char*)buffer );
143    LocalFree( buffer );
144    return msg;
145#elif NV_PLATFORM == NV_LINUX || NV_PLATFORM == NV_APPLE
146    return std::string(dlerror());
147#else
148    return std::string("");
149#endif
150}
Note: See TracBrowser for help on using the repository browser.