/* 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" | |
#include <mach-o/dyld.h> | |
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) | |
{ | |
dl_funcptr p = NULL; | |
char funcname[258]; | |
NSObjectFileImageReturnCode rc; | |
NSObjectFileImage image; | |
NSModule newModule; | |
NSSymbol theSym; | |
const char *errString; | |
char errBuf[512]; | |
PyOS_snprintf(funcname, sizeof(funcname), "_init%.200s", shortname); | |
#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 */ | |
errString = "Can't create object file image"; | |
break; | |
case NSObjectFileImageSuccess: | |
errString = NULL; | |
break; | |
case NSObjectFileImageInappropriateFile: | |
errString = "Inappropriate file type for dynamic loading"; | |
break; | |
case NSObjectFileImageArch: | |
errString = "Wrong CPU type in object file"; | |
break; | |
case NSObjectFileImageAccess: | |
errString = "Can't read object file (no access)"; | |
break; | |
} | |
if (errString == NULL) { | |
newModule = NSLinkModule(image, pathname, LINKOPTIONS); | |
if (newModule == NULL) { | |
int errNo; | |
const 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); removed: causes problems for ObjC code */ | |
PyErr_Format(PyExc_ImportError, | |
"Loaded module does not contain symbol %.200s", | |
funcname); | |
return NULL; | |
} | |
theSym = NSLookupAndBindSymbol(funcname); | |
#else | |
theSym = NSLookupSymbolInModule(newModule, funcname); | |
if ( theSym == NULL ) { | |
/* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */ | |
PyErr_Format(PyExc_ImportError, | |
"Loaded module does not contain symbol %.200s", | |
funcname); | |
return NULL; | |
} | |
#endif | |
p = (dl_funcptr)NSAddressOfSymbol(theSym); | |
return p; | |
} |