]> Dogcows Code - chaz/yoink/blob - src/stlplus/portability/dynaload.cpp
import stlplus 3.7
[chaz/yoink] / src / stlplus / portability / dynaload.cpp
1 ////////////////////////////////////////////////////////////////////////////////
2
3 // Author: Andy Rushton
4 // Copyright: (c) Southampton University 1999-2004
5 // (c) Andy Rushton 2004 onwards
6 // License: BSD License, see ../docs/license.html
7
8 ////////////////////////////////////////////////////////////////////////////////
9 #include "dynaload.hpp"
10
11 #ifdef MSWINDOWS
12 #include <windows.h>
13 #else
14 #include <dlfcn.h>
15 #endif
16
17 ////////////////////////////////////////////////////////////////////////////////
18
19 #ifdef MSWINDOWS
20
21 static std::string last_error(void)
22 {
23 // get the last error code - if none, return the empty string
24 DWORD err = GetLastError();
25 if (err == 0) return std::string();
26 // get the system message for this error code
27 char* message;
28 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
29 0,
30 err,
31 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
32 (LPTSTR)&message,
33 0,0);
34 std::string result = message;
35 LocalFree(message);
36 // the error message is for some perverse reason newline terminated - remove this
37 if (result[result.size()-1] == '\n')
38 result.erase(result.end()-1);
39 if (result[result.size()-1] == '\r')
40 result.erase(result.end()-1);
41 return result;
42 }
43
44 #else
45
46 static std::string last_error(void)
47 {
48 return std::string(dlerror());
49 }
50
51 #endif
52
53 ////////////////////////////////////////////////////////////////////////////////
54
55 namespace stlplus
56 {
57
58 ////////////////////////////////////////////////////////////////////////////////
59 // library management
60
61 // construct the object but do not load
62 dynaload::dynaload(void) : m_handle(0)
63 {
64 }
65
66 // construct and load
67 dynaload::dynaload(const std::string& library) : m_handle(0)
68 {
69 load(library);
70 }
71
72 // destroy and unload if loaded
73 dynaload::~dynaload(void)
74 {
75 unload();
76 }
77
78 // load the library - return success or fail
79 bool dynaload::load(const std::string& library)
80 {
81 #ifdef MSWINDOWS
82 m_handle = (void*)LoadLibraryA(library.c_str());
83 #elif defined(CYGWIN)
84 m_handle = dlopen(library.c_str(),RTLD_NOW);
85 #else
86 std::string full_library = std::string("lib") + library + std::string(".so");
87 m_handle = dlopen(full_library.c_str(),RTLD_NOW);
88 #endif
89 if (!m_handle)
90 {
91 m_error = load_error;
92 m_text = last_error();
93 }
94 return loaded();
95 }
96
97 // unload the library if loaded
98 bool dynaload::unload(void)
99 {
100 if (!loaded()) return false;
101 #ifdef MSWINDOWS
102 int status = FreeLibrary((HINSTANCE)m_handle) ? 0 : 1;
103 #else
104 int status = dlclose(m_handle);
105 #endif
106 if (status != 0)
107 {
108 m_error = unload_error;
109 m_text = last_error();
110 }
111 return status == 0;
112 }
113
114 // test whether the library is loaded
115 bool dynaload::loaded(void) const
116 {
117 return m_handle != 0;
118 }
119
120 ////////////////////////////////////////////////////////////////////////////
121 // symbol management
122
123 // test whether a function is exported by the library
124 // does not set the error flag if fails
125 bool dynaload::present(const std::string& name)
126 {
127 if (!loaded()) return false;
128 #ifdef MSWINDOWS
129 void* fn = (void*)GetProcAddress((HINSTANCE)m_handle,name.c_str());
130 #else
131 void* fn = dlsym(m_handle,name.c_str());
132 #endif
133 return fn != 0;
134 }
135
136 // get the function as a generic pointer
137 void* dynaload::symbol(const std::string& name)
138 {
139 if (!loaded()) return 0;
140 #ifdef MSWINDOWS
141 void* fn = (void*)GetProcAddress((HINSTANCE)m_handle,name.c_str());
142 #else
143 void* fn = dlsym(m_handle,name.c_str());
144 #endif
145 if (!fn)
146 {
147 m_error = symbol_error;
148 m_text = last_error();
149 }
150 return fn;
151 }
152
153 ////////////////////////////////////////////////////////////////////////////
154 // error management
155
156 // test whether there has been an error
157 bool dynaload::error(void) const
158 {
159 return m_error != no_error;
160 }
161
162 // clear an error once it has been handled (or ignored)
163 void dynaload::clear_error(void)
164 {
165 m_error = no_error;
166 m_text = std::string();
167 }
168
169 // get the type of the error as indicated by the enum error_t
170 dynaload::error_t dynaload::error_type(void) const
171 {
172 return m_error;
173 }
174
175 // get the text of the error as provided by the OS
176 std::string dynaload::error_text(void) const
177 {
178 return m_text;
179 }
180
181
182 ////////////////////////////////////////////////////////////////////////////////
183
184 } // end namespace stlplus
This page took 0.038802 seconds and 4 git commands to generate.