[Bf-committers] 2nd Try OS X Plugins Fix
Douglas Bischoff
bf-committers@blender.org
Tue, 2 Dec 2003 12:54:21 -0500
Hello all:
Okay, second try at fixing OS X plugins involves rewriting the dlopen()
series of functions in native OS X operations using the code from the
dlcompat library as a starting point.
I have contacted the author of dlcompat to ensure that his rights with
regards to his code are respected.
Here are 2 diff files that enable the revised method to work.
-Bischofftep
Index: bmake
===================================================================
RCS file: /cvsroot/bf-blender/blender/release/plugins/bmake,v
retrieving revision 1.5
diff -u -u -r1.5 bmake
--- bmake 25 Nov 2003 20:10:06 -0000 1.5
+++ bmake 2 Dec 2003 17:53:05 -0000
@@ -74,7 +74,7 @@
CC="cc";
CFLAGS="-fPIC -funsigned-char -O2 -fno-common";
LD="cc";
- LDFLAGS="-flat_namespace -bundle -bundle_loader
../../blender.app/Contents/MacOS/blender -ldl -lm";
+ LDFLAGS="-flat_namespace -bundle -bundle_loader
../../blender.app/Contents/MacOS/blender -lm";
EXT="so";
fi
Index: dynlib.c
===================================================================
RCS file:
/cvsroot/bf-blender/blender/source/blender/blenlib/intern/dynlib.c,v
retrieving revision 1.7
diff -u -u -r1.7 dynlib.c
--- dynlib.c 25 Nov 2003 20:10:06 -0000 1.7
+++ dynlib.c 2 Dec 2003 17:49:21 -0000
@@ -102,7 +102,203 @@
free(lib);
}
-#else /* Unix & MacOS X */
+#else
+#ifdef __APPLE__ /* MacOS X */
+
+#include <mach-o/dyld.h>
+#include <dlfcn.h>
+#include <stdarg.h>
+
+#define ERR_STR_LEN 256
+
+struct PILdynlib {
+ void *handle;
+};
+
+char *osxerror(int setget, const char *str, ...)
+{
+ static char errstr[ERR_STR_LEN];
+ static int err_filled = 0;
+ char *retval;
+ NSLinkEditErrors ler;
+ int lerno;
+ const char *dylderrstr;
+ const char *file;
+ va_list arg;
+ if (setget <= 0)
+ {
+ va_start(arg, str);
+ strncpy(errstr, "dlsimple: ", ERR_STR_LEN);
+ vsnprintf(errstr + 10, ERR_STR_LEN - 10, str, arg);
+ va_end(arg);
+ /* We prefer to use the dyld error string if setget is 0 */
+ if (setget == 0) {
+ NSLinkEditError(&ler, &lerno, &file, &dylderrstr);
+ printf("dyld: %s\n",dylderrstr);
+ if (dylderrstr && strlen(dylderrstr))
+ strncpy(errstr,dylderrstr,ERR_STR_LEN);
+ }
+ err_filled = 1;
+ retval = NULL;
+ }
+ else
+ {
+ if (!err_filled)
+ retval = NULL;
+ else
+ retval = errstr;
+ err_filled = 0;
+ }
+ return retval;
+}
+
+void *osxdlopen(const char *path, int mode)
+{
+ void *module = 0;
+ NSObjectFileImage ofi = 0;
+ NSObjectFileImageReturnCode ofirc;
+ static int (*make_private_module_public) (NSModule module) = 0;
+ unsigned int flags = NSLINKMODULE_OPTION_RETURN_ON_ERROR |
NSLINKMODULE_OPTION_PRIVATE;
+
+ /* If we got no path, the app wants the global namespace, use -1 as
the marker
+ in this case */
+ if (!path)
+ return (void *)-1;
+
+ /* Create the object file image, works for things linked with the
-bundle arg to ld */
+ ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
+ switch (ofirc)
+ {
+ case NSObjectFileImageSuccess:
+ /* It was okay, so use NSLinkModule to link in the image */
+ if (!(mode & RTLD_LAZY)) flags += NSLINKMODULE_OPTION_BINDNOW;
+ module = NSLinkModule(ofi, path,flags);
+ /* Don't forget to destroy the object file image, unless you like
leaks */
+ NSDestroyObjectFileImage(ofi);
+ /* If the mode was global, then change the module, this avoids
+ multiply defined symbol errors to first load private then make
+ global. Silly, isn't it. */
+ if ((mode & RTLD_GLOBAL))
+ {
+ if (!make_private_module_public)
+ {
+ _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",
+ (unsigned long *)&make_private_module_public);
+ }
+ make_private_module_public(module);
+ }
+ break;
+ case NSObjectFileImageInappropriateFile:
+ /* It may have been a dynamic library rather than a bundle, try to
load it */
+ module = (void *)NSAddImage(path,
NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+ break;
+ case NSObjectFileImageFailure:
+ osxerror(0,"Object file setup failure : \"%s\"", path);
+ return 0;
+ case NSObjectFileImageArch:
+ osxerror(0,"No object for this architecture : \"%s\"", path);
+ return 0;
+ case NSObjectFileImageFormat:
+ osxerror(0,"Bad object file format : \"%s\"", path);
+ return 0;
+ case NSObjectFileImageAccess:
+ osxerror(0,"Can't read object file : \"%s\"", path);
+ return 0;
+ }
+ if (!module)
+ osxerror(0, "Can not open \"%s\"", path);
+ return module;
+}
+
+PILdynlib *PIL_dynlib_open(char *name) {
+ void *handle= osxdlopen(name, RTLD_LAZY);
+
+ if (handle) {
+ PILdynlib *lib= malloc(sizeof(*lib));
+ lib->handle= handle;
+
+ return lib;
+ } else {
+ return NULL;
+ }
+}
+
+void *PIL_dynlib_find_symbol(PILdynlib* lib, char *symname)
+{
+ int sym_len = strlen(symname);
+ void *value = NULL;
+ char *malloc_sym = NULL;
+ NSSymbol *nssym = 0;
+ malloc_sym = malloc(sym_len + 2);
+ if (malloc_sym)
+ {
+ sprintf(malloc_sym, "_%s", symname);
+ /* If the lib->handle is -1, if is the app global context */
+ if (lib->handle == (void *)-1)
+ {
+ /* Global context, use NSLookupAndBindSymbol */
+ if (NSIsSymbolNameDefined(malloc_sym))
+ {
+ nssym = NSLookupAndBindSymbol(malloc_sym);
+ }
+ }
+ /* Now see if the lib->handle is a struch mach_header* or not, use
NSLookupSymbol in image
+ for libraries, and NSLookupSymbolInModule for bundles */
+ else
+ {
+ /* Check for both possible magic numbers depending on x86/ppc byte
order */
+ if ((((struct mach_header *)lib->handle)->magic == MH_MAGIC) ||
+ (((struct mach_header *)lib->handle)->magic == MH_CIGAM))
+ {
+ if (NSIsSymbolNameDefinedInImage((struct mach_header
*)lib->handle, malloc_sym))
+ {
+ nssym = NSLookupSymbolInImage((struct mach_header *)lib->handle,
+ malloc_sym,
+ NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
+ | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
+ }
+
+ }
+ else
+ {
+ nssym = NSLookupSymbolInModule(lib->handle, malloc_sym);
+ }
+ }
+ if (!nssym)
+ {
+ osxerror(0, "symname \"%s\" Not found", symname);
+ }
+ value = NSAddressOfSymbol(nssym);
+ free(malloc_sym);
+ }
+ else
+ {
+ osxerror(-1, "Unable to allocate memory");
+ }
+ return value;
+}
+
+char *PIL_dynlib_get_error_as_string(PILdynlib* lib)
+{
+ return osxerror(1, (char *)NULL);
+}
+
+void PIL_dynlib_close(PILdynlib *lib)
+{
+ if ((((struct mach_header *)lib->handle)->magic == MH_MAGIC) ||
+ (((struct mach_header *)lib->handle)->magic == MH_CIGAM))
+ {
+ osxerror(-1, "Can't remove dynamic libraries on darwin");
+ }
+ if (!NSUnLinkModule(lib->handle, 0))
+ {
+ osxerror(0, "unable to unlink module %s",
NSNameOfModule(lib->handle));
+ }
+
+ free(lib);
+}
+
+#else /* Unix */
#include <dlfcn.h>
@@ -137,4 +333,5 @@
free(lib);
}
+#endif
#endif