]> granicus.if.org Git - python/commitdiff
A new dynload_next, which actually only works on OSX but isn't renamed yet.
authorJack Jansen <jack.jansen@cwi.nl>
Fri, 1 Feb 2002 16:01:05 +0000 (16:01 +0000)
committerJack Jansen <jack.jansen@cwi.nl>
Fri, 1 Feb 2002 16:01:05 +0000 (16:01 +0000)
By default every module is imported in its own namespace, but this can
be changed by defining USE_DYLD_GLOBAL_NAMESPACE. In a future version this
define will be replaced by a runtime setting, but that needs a bit more
thought.

This code is largely based on code and feedback from Steven Majewski,
Marcel Prastawa, Manoj Plakal and other on pythonmac-sig.

Python/dynload_next.c

index 892bb478424b261086363bf56c955426c3f41a52..9dec4656987b002b6155dfcad042bf4d75696e20 100644 (file)
 
-/* Support for dynamic loading of extension modules */
+/* Support for dynamic loading of extension modules on Mac OS X
+** All references to "NeXT" are for historical reasons.
+*/
 
 #include "Python.h"
 #include "importdl.h"
 
-
-#ifdef WITH_DYLD
-
-#define USE_DYLD
-
 #include <mach-o/dyld.h>
 
-#else /* WITH_DYLD */
-
-#define USE_RLD
-/* Define this to 1 if you want be able to load ObjC modules as well:
-   it switches between two different way of loading modules on the NeXT,
-   one that directly interfaces with the dynamic loader (rld_load(), which
-   does not correctly load ObjC object files), and another that uses the
-   ObjC runtime (objc_loadModules()) to do the job.
-   You'll have to add ``-ObjC'' to the compiler flags if you set this to 1.
-*/
-#define HANDLE_OBJC_MODULES 1
-#if HANDLE_OBJC_MODULES
-#include <objc/Object.h>
-#include <objc/objc-load.h>
-#endif
-
-#include <mach-o/rld.h>
-
-#endif /* WITH_DYLD */
-
-
 const struct filedescr _PyImport_DynLoadFiletab[] = {
        {".so", "rb", C_EXTENSION},
        {"module.so", "rb", C_EXTENSION},
        {0, 0}
 };
 
+/*
+** Python modules are Mach-O MH_BUNDLE files. The best way to load these
+** is each in a private namespace, so you can load, say, a module bar and a
+** module foo.bar. If we load everything in the global namespace the two
+** initbar() symbols will conflict.
+** However, it seems some extension packages depend upon being able to access
+** each others' global symbols. There seems to be no way to eat our cake and
+** have it, so the USE_DYLD_GLOBAL_NAMESPACE define determines which behaviour
+** you get.
+*/
+
+#ifdef USE_DYLD_GLOBAL_NAMESPACE
+#define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR
+#else
+#define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW| \
+       NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE
+#endif
 dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
-                                   const char *pathname, FILE *fp)
+                                       const char *pathname, FILE *fp)
 {
        dl_funcptr p = NULL;
        char funcname[258];
 
        PyOS_snprintf(funcname, sizeof(funcname), "_init%.200s", shortname);
 
-#ifdef USE_RLD
-       {
-               NXStream *errorStream;
-               struct mach_header *new_header;
-               const char *filenames[2];
-               long ret;
-               unsigned long ptr;
-
-               errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
-               filenames[0] = pathname;
-               filenames[1] = NULL;
-
-#if HANDLE_OBJC_MODULES
-
-/* The following very bogus line of code ensures that
-   objc_msgSend, etc are linked into the binary.  Without
-   it, dynamic loading of a module that includes objective-c
-   method calls will fail with "undefined symbol _objc_msgSend()".
-   This remains true even in the presence of the -ObjC flag
-   to the compiler
-*/
-
-               [Object name];
-
-/* objc_loadModules() dynamically loads the object files
-   indicated by the paths in filenames.  If there are any
-   errors generated during loading -- typically due to the
-   inability to find particular symbols -- an error message
-   will be written to errorStream.
-   It returns 0 if the module is successfully loaded, 1
-   otherwise.
-*/
-
-               ret = !objc_loadModules(filenames, errorStream,
-                                       NULL, &new_header, NULL);
-
-#else /* !HANDLE_OBJC_MODULES */
-
-               ret = rld_load(errorStream, &new_header, 
-                               filenames, NULL);
-
-#endif /* HANDLE_OBJC_MODULES */
-
-               /* extract the error messages for the exception */
-               if(!ret) {
-                       char *streamBuf;
-                       int len, maxLen;
-
-                       NXPutc(errorStream, (char)0);
-
-                       NXGetMemoryBuffer(errorStream,
-                               &streamBuf, &len, &maxLen);
-                       PyErr_SetString(PyExc_ImportError, streamBuf);
-               }
-
-               if(ret && rld_lookup(errorStream, funcname, &ptr))
-                       p = (dl_funcptr) ptr;
-
-               NXCloseMemory(errorStream, NX_FREEBUFFER);
-
-               if(!ret)
-                       return NULL;
-       }
-#endif /* USE_RLD */
-#ifdef USE_DYLD
-       /* This is also NeXT-specific. However, frameworks (the new style
-       of shared library) and rld() can't be used in the same program;
-       instead, you have to use dyld, which is mostly unimplemented. */
        {
                NSObjectFileImageReturnCode rc;
                NSObjectFileImage image;
                NSModule newModule;
                NSSymbol theSym;
                const char *errString;
+               char errBuf[512];
        
+#ifdef USE_DYLD_GLOBAL_NAMESPACE
                if (NSIsSymbolNameDefined(funcname)) {
                        theSym = NSLookupAndBindSymbol(funcname);
                        p = (dl_funcptr)NSAddressOfSymbol(theSym);
                        return p;
                }
+#endif
                rc = NSCreateObjectFileImageFromFile(pathname, &image);
                switch(rc) {
-                   default:
-                   case NSObjectFileImageFailure:
-                   case NSObjectFileImageFormat:
-                   /* for these a message is printed on stderr by dyld */
+                       default:
+                       case NSObjectFileImageFailure:
+                       case NSObjectFileImageFormat:
+                       /* for these a message is printed on stderr by dyld */
                        errString = "Can't create object file image";
                        break;
-                   case NSObjectFileImageSuccess:
+                       case NSObjectFileImageSuccess:
                        errString = NULL;
                        break;
-                   case NSObjectFileImageInappropriateFile:
+                       case NSObjectFileImageInappropriateFile:
                        errString = "Inappropriate file type for dynamic loading";
                        break;
-                   case NSObjectFileImageArch:
+                       case NSObjectFileImageArch:
                        errString = "Wrong CPU type in object file";
                        break;
-                   case NSObjectFileImageAccess:
+                       case NSObjectFileImageAccess:
                        errString = "Can't read object file (no access)";
                        break;
                }
                if (errString == NULL) {
-                       newModule = NSLinkModule(image, pathname,
-                               NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR);
-                       if (!newModule)
-                               errString = "Failure linking new module";
+                       newModule = NSLinkModule(image, pathname, LINKOPTIONS);
+                       if (newModule == NULL) {
+                               int errNo;
+                               char *fileName, *moreErrorStr;
+                               NSLinkEditErrors c;
+                               NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr );
+                               PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s", 
+                                               fileName, moreErrorStr);
+                               errString = errBuf;
+                       }
                }
                if (errString != NULL) {
                        PyErr_SetString(PyExc_ImportError, errString);
                        return NULL;
                }
+#ifdef USE_DYLD_GLOBAL_NAMESPACE
                if (!NSIsSymbolNameDefined(funcname)) {
                        /* UnlinkModule() isn't implemented in current versions, but calling it does no harm */
                        NSUnLinkModule(newModule, FALSE);
                        PyErr_Format(PyExc_ImportError,
-                                    "Loaded module does not contain symbol %.200s",
-                                    funcname);
+                                        "Loaded module does not contain symbol %.200s",
+                                        funcname);
                        return NULL;
                }
                theSym = NSLookupAndBindSymbol(funcname);
+#else
+               theSym = NSLookupSymbolInModule(newModule, funcname);
+               if ( theSym == NULL ) {
+                       NSUnLinkModule(newModule, FALSE);
+                       PyErr_Format(PyExc_ImportError,
+                                        "Loaded module does not contain symbol %.200s",
+                                        funcname);
+                       return NULL;
+               }
+#endif
                p = (dl_funcptr)NSAddressOfSymbol(theSym);
-       }
-#endif /* USE_DYLD */
+       }
 
        return p;
 }