]> git.saurik.com Git - wxWidgets.git/blob - src/unix/dlunix.cpp
extracted Unix code in a separate new file (src/unix/dlunix.cpp), it remains only...
[wxWidgets.git] / src / unix / dlunix.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: unix/dlunix.cpp
3 // Purpose: Unix-specific part of wxDynamicLibrary and related classes
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 2005-01-16 (extracted from common/dynlib.cpp)
7 // RCS-ID: $Id$
8 // Copyright: (c) 2000-2005 Vadim Zeitlin <vadim@wxwindows.org>
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #if wxUSE_DYNLIB_CLASS
27
28 #include "wx/dynlib.h"
29
30 #if defined(HAVE_DLOPEN) || defined(__DARWIN__)
31 #define USE_POSIX_DL_FUNCS
32 #elif !defined(HAVE_SHL_LOAD)
33 #error "Don't know how to load dynamic libraries on this platform!"
34 #endif
35
36 // ----------------------------------------------------------------------------
37 // constants
38 // ----------------------------------------------------------------------------
39
40 // standard shared libraries extensions for different Unix versions
41 #if defined(__HPUX__)
42 const wxChar *wxDynamicLibrary::ms_dllext = _T(".sl");
43 #elif defined(__DARWIN__)
44 const wxChar *wxDynamicLibrary::ms_dllext = _T(".bundle");
45 #else
46 const wxChar *wxDynamicLibrary::ms_dllext = _T(".so");
47 #endif
48
49 // ============================================================================
50 // wxDynamicLibrary implementation
51 // ============================================================================
52
53 // ----------------------------------------------------------------------------
54 // dlxxx() emulation for Darwin
55 // ----------------------------------------------------------------------------
56
57 #if defined(__DARWIN__)
58 // ---------------------------------------------------------------------------
59 // For Darwin/Mac OS X
60 // supply the sun style dlopen functions in terms of Darwin NS*
61 // ---------------------------------------------------------------------------
62
63 /* Porting notes:
64 * The dlopen port is a port from dl_next.xs by Anno Siegel.
65 * dl_next.xs is itself a port from dl_dlopen.xs by Paul Marquess.
66 * The method used here is just to supply the sun style dlopen etc.
67 * functions in terms of Darwin NS*.
68 */
69
70 #include <stdio.h>
71 #include <mach-o/dyld.h>
72
73 static char dl_last_error[1024];
74
75 static
76 void TranslateError(const char *path, int number)
77 {
78 unsigned int index;
79 static char *OFIErrorStrings[] =
80 {
81 "%s(%d): Object Image Load Failure\n",
82 "%s(%d): Object Image Load Success\n",
83 "%s(%d): Not an recognisable object file\n",
84 "%s(%d): No valid architecture\n",
85 "%s(%d): Object image has an invalid format\n",
86 "%s(%d): Invalid access (permissions?)\n",
87 "%s(%d): Unknown error code from NSCreateObjectFileImageFromFile\n",
88 };
89 #define NUM_OFI_ERRORS (sizeof(OFIErrorStrings) / sizeof(OFIErrorStrings[0]))
90
91 index = number;
92 if (index > NUM_OFI_ERRORS - 1) {
93 index = NUM_OFI_ERRORS - 1;
94 }
95 sprintf(dl_last_error, OFIErrorStrings[index], path, number);
96 }
97
98 const char *dlerror()
99 {
100 return dl_last_error;
101 }
102
103 void *dlopen(const char *path, int WXUNUSED(mode) /* mode is ignored */)
104 {
105 NSObjectFileImage ofile;
106 NSModule handle = NULL;
107
108 int dyld_result = NSCreateObjectFileImageFromFile(path, &ofile);
109 if ( dyld_result != NSObjectFileImageSuccess )
110 {
111 handle = NULL;
112 }
113 else
114 {
115 handle = NSLinkModule
116 (
117 ofile,
118 path,
119 NSLINKMODULE_OPTION_BINDNOW |
120 NSLINKMODULE_OPTION_RETURN_ON_ERROR
121 );
122 }
123
124 if ( !handle )
125 TranslateError(path, dyld_result);
126
127 return handle;
128 }
129
130 int dlclose(void *handle)
131 {
132 NSUnLinkModule( handle, NSUNLINKMODULE_OPTION_NONE);
133 return 0;
134 }
135
136 void *dlsym(void *handle, const char *symbol)
137 {
138 // as on many other systems, C symbols have prepended underscores under
139 // Darwin but unlike the normal dlopen(), NSLookupSymbolInModule() is not
140 // aware of this
141 wxCharBuffer buf(strlen(symbol) + 1);
142 char *p = buf.data();
143 p[0] = '_';
144 strcpy(p + 1, symbol);
145
146 NSSymbol nsSymbol = NSLookupSymbolInModule( handle, p );
147 return nsSymbol ? NSAddressOfSymbol(nsSymbol) : NULL;
148 }
149
150 #endif // defined(__DARWIN__)
151
152 // ----------------------------------------------------------------------------
153 // loading/unloading DLLs
154 // ----------------------------------------------------------------------------
155
156 wxDllType wxDynamicLibrary::GetProgramHandle()
157 {
158 #ifdef USE_POSIX_DL_FUNCS
159 return dlopen(0, RTLD_LAZY);
160 #else
161 return PROG_HANDLE;
162 #endif
163 }
164
165 /* static */
166 wxDllType wxDynamicLibrary::RawLoad(const wxString& libname, int flags)
167 {
168 wxASSERT_MSG( (flags & wxDL_NOW) == 0,
169 _T("wxDL_LAZY and wxDL_NOW are mutually exclusive.") );
170
171 #ifdef USE_POSIX_DL_FUNCS
172 int rtldFlags = 0;
173
174 #ifdef RTLD_LAZY
175 if ( flags & wxDL_LAZY )
176 {
177 rtldFlags |= RTLD_LAZY;
178 }
179 #endif
180 #ifdef RTLD_NOW
181 if ( flags & wxDL_NOW )
182 {
183 rtldFlags |= RTLD_NOW;
184 }
185 #endif
186 #ifdef RTLD_GLOBAL
187 if ( flags & wxDL_GLOBAL )
188 {
189 rtldFlags |= RTLD_GLOBAL;
190 }
191 #endif
192
193 return dlopen(libname.fn_str(), rtldFlags);
194 #else // !USE_POSIX_DL_FUNCS
195 int shlFlags = 0;
196
197 if ( flags & wxDL_LAZY )
198 {
199 shlFlags |= BIND_DEFERRED;
200 }
201 else if ( flags & wxDL_NOW )
202 {
203 shlFlags |= BIND_IMMEDIATE;
204 }
205
206 return shl_load(libname.fn_str(), shlFlags, 0);
207 #endif // USE_POSIX_DL_FUNCS/!USE_POSIX_DL_FUNCS
208 }
209
210 /* static */
211 void wxDynamicLibrary::Unload(wxDllType handle)
212 {
213 #ifdef wxHAVE_DYNLIB_ERROR
214 int rc =
215 #endif
216
217 #ifdef USE_POSIX_DL_FUNCS
218 dlclose(handle);
219 #else // !USE_POSIX_DL_FUNCS
220 shl_unload(handle);
221 #endif // USE_POSIX_DL_FUNCS/!USE_POSIX_DL_FUNCS
222
223 #ifdef USE_POSIX_DL_FUNCS
224 if ( rc != 0 )
225 Error();
226 #endif
227 }
228
229 /* static */
230 void *wxDynamicLibrary::RawGetSymbol(wxDllType handle, const wxString& name)
231 {
232 void *symbol;
233
234 #ifdef USE_POSIX_DL_FUNCS
235 symbol = dlsym(handle, name.fn_str());
236 #else // !USE_POSIX_DL_FUNCS
237 // note that shl_findsym modifies the handle argument to indicate where the
238 // symbol was found, but it's ok to modify the local handle copy here
239 if ( shl_findsym(&handle, name.fn_str(), TYPE_UNDEFINED, &symbol) != 0 )
240 symbol = 0;
241 #endif // USE_POSIX_DL_FUNCS/!USE_POSIX_DL_FUNCS
242
243 return symbol;
244 }
245
246 #ifdef wxHAVE_DYNLIB_ERROR
247
248 /* static */
249 void wxDynamicLibrary::Error()
250 {
251 #if wxUSE_UNICODE
252 wxWCharBuffer buffer = wxConvLocal.cMB2WC( dlerror() );
253 const wxChar *err = buffer;
254 #else
255 const wxChar *err = dlerror();
256 #endif
257
258 wxLogError(wxT("%s"), err ? err : _("Unknown dynamic library error"));
259 }
260
261 #endif // wxHAVE_DYNLIB_ERROR
262
263 #endif // wxUSE_DYNLIB_CLASS
264