Home | History | Annotate | Download | only in Python
      1 
      2 /* Support for dynamic loading of extension modules on Mac OS X
      3 ** All references to "NeXT" are for historical reasons.
      4 */
      5 
      6 #include "Python.h"
      7 #include "importdl.h"
      8 
      9 #include <mach-o/dyld.h>
     10 
     11 const struct filedescr _PyImport_DynLoadFiletab[] = {
     12     {".so", "rb", C_EXTENSION},
     13     {"module.so", "rb", C_EXTENSION},
     14     {0, 0}
     15 };
     16 
     17 /*
     18 ** Python modules are Mach-O MH_BUNDLE files. The best way to load these
     19 ** is each in a private namespace, so you can load, say, a module bar and a
     20 ** module foo.bar. If we load everything in the global namespace the two
     21 ** initbar() symbols will conflict.
     22 ** However, it seems some extension packages depend upon being able to access
     23 ** each others' global symbols. There seems to be no way to eat our cake and
     24 ** have it, so the USE_DYLD_GLOBAL_NAMESPACE define determines which behaviour
     25 ** you get.
     26 */
     27 
     28 #ifdef USE_DYLD_GLOBAL_NAMESPACE
     29 #define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR
     30 #else
     31 #define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW| \
     32     NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE
     33 #endif
     34 dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
     35                                         const char *pathname, FILE *fp)
     36 {
     37     dl_funcptr p = NULL;
     38     char funcname[258];
     39     NSObjectFileImageReturnCode rc;
     40     NSObjectFileImage image;
     41     NSModule newModule;
     42     NSSymbol theSym;
     43     const char *errString;
     44     char errBuf[512];
     45 
     46     PyOS_snprintf(funcname, sizeof(funcname), "_init%.200s", shortname);
     47 
     48 #ifdef USE_DYLD_GLOBAL_NAMESPACE
     49     if (NSIsSymbolNameDefined(funcname)) {
     50         theSym = NSLookupAndBindSymbol(funcname);
     51         p = (dl_funcptr)NSAddressOfSymbol(theSym);
     52         return p;
     53     }
     54 #endif
     55     rc = NSCreateObjectFileImageFromFile(pathname, &image);
     56     switch(rc) {
     57         default:
     58         case NSObjectFileImageFailure:
     59         case NSObjectFileImageFormat:
     60             /* for these a message is printed on stderr by dyld */
     61             errString = "Can't create object file image";
     62         break;
     63         case NSObjectFileImageSuccess:
     64             errString = NULL;
     65             break;
     66         case NSObjectFileImageInappropriateFile:
     67             errString = "Inappropriate file type for dynamic loading";
     68             break;
     69         case NSObjectFileImageArch:
     70             errString = "Wrong CPU type in object file";
     71             break;
     72         case NSObjectFileImageAccess:
     73             errString = "Can't read object file (no access)";
     74             break;
     75     }
     76     if (errString == NULL) {
     77         newModule = NSLinkModule(image, pathname, LINKOPTIONS);
     78         if (newModule == NULL) {
     79             int errNo;
     80             const char *fileName, *moreErrorStr;
     81             NSLinkEditErrors c;
     82             NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr );
     83             PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s",
     84                             fileName, moreErrorStr);
     85             errString = errBuf;
     86         }
     87     }
     88     if (errString != NULL) {
     89         PyErr_SetString(PyExc_ImportError, errString);
     90         return NULL;
     91     }
     92 #ifdef USE_DYLD_GLOBAL_NAMESPACE
     93     if (!NSIsSymbolNameDefined(funcname)) {
     94         /* UnlinkModule() isn't implemented in current versions, but calling it does no harm */
     95         /* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
     96         PyErr_Format(PyExc_ImportError,
     97                          "Loaded module does not contain symbol %.200s",
     98                          funcname);
     99         return NULL;
    100     }
    101     theSym = NSLookupAndBindSymbol(funcname);
    102 #else
    103     theSym = NSLookupSymbolInModule(newModule, funcname);
    104     if ( theSym == NULL ) {
    105         /* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
    106         PyErr_Format(PyExc_ImportError,
    107                          "Loaded module does not contain symbol %.200s",
    108                          funcname);
    109         return NULL;
    110     }
    111 #endif
    112     p = (dl_funcptr)NSAddressOfSymbol(theSym);
    113     return p;
    114 }
    115