Uncommented beaudio code
[pwlib.git] / src / ptlib / unix / udll.cxx
blob92ec0c61cc8097d6e1b0b0cb3f716b90484f77a6
1 /*
2 * udll.cxx
4 * Dynamic Link Library implementation.
6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
29 * $Log$
30 * Revision 1.16 2003/09/11 00:52:13 dereksmithies
31 * Full dependancy check on dynamically loading a library.
32 * Thanks to Snark on #gnomemeeting for pointing this out...
34 * Revision 1.15 2003/07/09 11:37:13 rjongbloed
35 * Fixed corrct closing of DLL (setting handle to NULL) thanks Fabrizio Ammollo
37 * Revision 1.14 2003/05/14 10:50:30 dereksmithies
38 * Quick hack to add the function: PDynaLink::GetName(). Fix me.
40 * Revision 1.13 2003/05/06 06:59:12 robertj
41 * Dynamic library support for MacOSX, thanks Hugo Santos
43 * Revision 1.12 2003/04/16 07:17:35 craigs
44 * CHanged to use new #define
46 * Revision 1.11 2001/06/30 06:59:07 yurik
47 * Jac Goudsmit from Be submit these changes 6/28. Implemented by Yuri Kiryanov
49 * Revision 1.10 2001/03/07 06:57:52 yurik
50 * Changed email to current one
52 * Revision 1.9 2000/03/10 08:21:17 rogerh
53 * Add correct OpenBSD support
55 * Revision 1.8 2000/03/09 18:41:53 rogerh
56 * Workaround for OpenBSD. This breaks the functionality on OpenBSD but
57 * gains us a clean compilation. We can return to this problem later.
59 * Revision 1.7 1999/02/22 13:26:54 robertj
60 * BeOS port changes.
62 * Revision 1.6 1999/02/06 05:49:44 robertj
63 * BeOS port effort by Yuri Kiryanov <openh323@kiryanov.com>
65 * Revision 1.5 1998/11/30 21:52:03 robertj
66 * New directory structure.
68 * Revision 1.4 1998/09/24 04:12:26 robertj
69 * Added open software license.
71 * Revision 1.3 1998/01/04 08:11:41 craigs
72 * Remove Solarisism and made platform independent
74 * Revision 1.2 1997/10/30 12:41:22 craigs
75 * Added GetExtension command
77 * Revision 1.1 1997/04/22 10:58:17 craigs
78 * Initial revision
83 #pragma implementation "dynalink.h"
85 #include <ptlib.h>
87 #ifdef P_MACOSX
90 Copyright (c) 2002 Peter O'Gorman <ogorman@users.sourceforge.net>
92 Permission is hereby granted, free of charge, to any person obtaining
93 a copy of this software and associated documentation files (the
94 "Software"), to deal in the Software without restriction, including
95 without limitation the rights to use, copy, modify, merge, publish,
96 distribute, sublicense, and/or sell copies of the Software, and to
97 permit persons to whom the Software is furnished to do so, subject to
98 the following conditions:
100 The above copyright notice and this permission notice shall be
101 included in all copies or substantial portions of the Software.
103 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
104 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
105 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
106 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
107 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
108 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
109 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
113 /* Just to prove that it isn't that hard to add Mac calls to your code :)
114 This works with pretty much everything, including kde3 xemacs and the gimp,
115 I'd guess that it'd work in at least 95% of cases, use this as your starting
116 point, rather than the mess that is dlfcn.c, assuming that your code does not
117 require ref counting or symbol lookups in dependent libraries
120 #include <stdio.h>
121 #include <stdlib.h>
122 #include <string.h>
123 #include <sys/types.h>
124 #include <sys/stat.h>
125 #include <stdarg.h>
126 #include <limits.h>
127 #include <mach-o/dyld.h>
129 #define RTLD_LAZY 0x1
130 #define RTLD_NOW 0x2
131 #define RTLD_LOCAL 0x4
132 #define RTLD_GLOBAL 0x8
133 #define RTLD_NOLOAD 0x10
134 #define RTLD_NODELETE 0x80
136 #define ERR_STR_LEN 256
138 static void *dlsymIntern(void *handle, const char *symbol);
140 static const char *error(int setget, const char *str, ...);
144 /* Set and get the error string for use by dlerror */
145 static const char *error(int setget, const char *str, ...)
147 static char errstr[ERR_STR_LEN];
148 static int err_filled = 0;
149 const char *retval;
150 va_list arg;
151 if (setget == 0)
153 va_start(arg, str);
154 strncpy(errstr, "dlsimple: ", ERR_STR_LEN);
155 vsnprintf(errstr + 10, ERR_STR_LEN - 10, str, arg);
156 va_end(arg);
157 err_filled = 1;
158 retval = NULL;
160 else
162 if (!err_filled)
163 retval = NULL;
164 else
165 retval = errstr;
166 err_filled = 0;
168 return retval;
171 /* dlopen */
172 static void *dlopen(const char *path, int mode)
174 void *module = 0;
175 NSObjectFileImage ofi = 0;
176 NSObjectFileImageReturnCode ofirc;
177 static int (*make_private_module_public) (NSModule module) = 0;
178 unsigned int flags = NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_PRIVATE;
180 /* If we got no path, the app wants the global namespace, use -1 as the marker
181 in this case */
182 if (!path)
183 return (void *)-1;
185 /* Create the object file image, works for things linked with the -bundle arg to ld */
186 ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
187 switch (ofirc)
189 case NSObjectFileImageSuccess:
190 /* It was okay, so use NSLinkModule to link in the image */
191 if (!(mode & RTLD_LAZY)) flags += NSLINKMODULE_OPTION_BINDNOW;
192 module = NSLinkModule(ofi, path,flags);
193 /* Don't forget to destroy the object file image, unless you like leaks */
194 NSDestroyObjectFileImage(ofi);
195 /* If the mode was global, then change the module, this avoids
196 multiply defined symbol errors to first load private then make
197 global. Silly, isn't it. */
198 if ((mode & RTLD_GLOBAL))
200 if (!make_private_module_public)
202 _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",
203 (unsigned long *)&make_private_module_public);
205 make_private_module_public(module);
207 break;
208 case NSObjectFileImageInappropriateFile:
209 /* It may have been a dynamic library rather than a bundle, try to load it */
210 module = (void *)NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
211 break;
212 case NSObjectFileImageFailure:
213 error(0,"Object file setup failure : \"%s\"", path);
214 return 0;
215 case NSObjectFileImageArch:
216 error(0,"No object for this architecture : \"%s\"", path);
217 return 0;
218 case NSObjectFileImageFormat:
219 error(0,"Bad object file format : \"%s\"", path);
220 return 0;
221 case NSObjectFileImageAccess:
222 error(0,"Can't read object file : \"%s\"", path);
223 return 0;
225 if (!module)
226 error(0, "Can not open \"%s\"", path);
227 return module;
230 /* dlsymIntern is used by dlsym to find the symbol */
231 static void *dlsymIntern(void *handle, const char *symbol)
233 NSSymbol *nssym = 0;
234 /* If the handle is -1, if is the app global context */
235 if (handle == (void *)-1)
237 /* Global context, use NSLookupAndBindSymbol */
238 if (NSIsSymbolNameDefined(symbol))
240 nssym = NSLookupAndBindSymbol(symbol);
244 /* Now see if the handle is a struch mach_header* or not, use NSLookupSymbol in image
245 for libraries, and NSLookupSymbolInModule for bundles */
246 else
248 /* Check for both possible magic numbers depending on x86/ppc byte order */
249 if ((((struct mach_header *)handle)->magic == MH_MAGIC) ||
250 (((struct mach_header *)handle)->magic == MH_CIGAM))
252 if (NSIsSymbolNameDefinedInImage((struct mach_header *)handle, symbol))
254 nssym = NSLookupSymbolInImage((struct mach_header *)handle,
255 symbol,
256 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
257 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
261 else
263 nssym = NSLookupSymbolInModule(handle, symbol);
266 if (!nssym)
268 error(0, "Symbol \"%s\" Not found", symbol);
269 return NULL;
271 return NSAddressOfSymbol(nssym);
274 static const char *dlerror(void)
276 return error(1, (char *)NULL);
279 static int dlclose(void *handle)
281 if ((((struct mach_header *)handle)->magic == MH_MAGIC) ||
282 (((struct mach_header *)handle)->magic == MH_CIGAM))
284 error(0, "Can't remove dynamic libraries on darwin");
285 return 0;
287 if (!NSUnLinkModule(handle, 0))
289 error(0, "unable to unlink module %s", NSNameOfModule(handle));
290 return 1;
292 return 0;
296 /* dlsym, prepend the underscore and call dlsymIntern */
297 static void *dlsym(void *handle, const char *symbol)
299 static char undersym[257]; /* Saves calls to malloc(3) */
300 int sym_len = strlen(symbol);
301 void *value = NULL;
302 char *malloc_sym = NULL;
304 if (sym_len < 256)
306 snprintf(undersym, 256, "_%s", symbol);
307 value = dlsymIntern(handle, undersym);
309 else
311 malloc_sym = malloc(sym_len + 2);
312 if (malloc_sym)
314 sprintf(malloc_sym, "_%s", symbol);
315 value = dlsymIntern(handle, malloc_sym);
316 free(malloc_sym);
318 else
320 error(0, "Unable to allocate memory");
323 return value;
326 #endif
328 #ifndef P_DYNALINK
330 #warning "No implementation for dynamic library functions"
332 #else
334 PDynaLink::PDynaLink()
336 dllHandle = NULL;
339 PDynaLink::PDynaLink(const PString & name)
341 dllHandle = NULL;
342 Open(name);
345 PDynaLink::~PDynaLink()
347 Close();
350 PString PDynaLink::GetExtension()
352 return PString(".so");
355 BOOL PDynaLink::Open(const PString & name)
357 Close();
359 #if defined(P_OPENBSD)
360 dllHandle = dlopen((char *)(const char *)name, RTLD_NOW);
361 #else
362 dllHandle = dlopen((const char *)name, RTLD_NOW);
363 #endif
365 return IsLoaded();
368 void PDynaLink::Close()
370 if (dllHandle != NULL) {
371 dlclose(dllHandle);
372 dllHandle = NULL;
376 BOOL PDynaLink::IsLoaded() const
378 return dllHandle != NULL;
381 PString PDynaLink::GetName(BOOL full) const
383 if (!IsLoaded())
384 return "";
386 return "loaded";
390 BOOL PDynaLink::GetFunction(PINDEX, Function &)
392 return FALSE;
395 BOOL PDynaLink::GetFunction(const PString & name, Function & func)
397 if (dllHandle == NULL)
398 return FALSE;
400 #if defined(P_OPENBSD)
401 void * p = dlsym(dllHandle, (char *)(const char *)name);
402 #else
403 void * p = dlsym(dllHandle, (const char *)name);
404 #endif
406 if (p == NULL)
407 return FALSE;
409 func = (Function &)p;
410 return TRUE;
413 #endif
415 // End of file