/* Support for dynamic loading of extension modules */ #include "Python.h" #include "importdl.h" #ifdef WITH_DYLD #define USE_DYLD #include #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 #include #endif #include #endif /* WITH_DYLD */ const struct filedescr _PyImport_DynLoadFiletab[] = { {".so", "rb", C_EXTENSION}, {"module.so", "rb", C_EXTENSION}, {0, 0} }; dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, const char *pathname, FILE *fp) { dl_funcptr p = NULL; char funcname[258]; sprintf(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; void *symaddr; const char *errString; rc = NSCreateObjectFileImageFromFile(pathname, &image); switch(rc) { default: case NSObjectFileImageFailure: 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; NSObjectFileImageAccess: errString = "Can't read object file (no access)"; break; } if (errString == NULL) { newModule = NSLinkModule(image, pathname, TRUE); if (!newModule) errString = "Failure linking new module"; } if (errString != NULL) { PyErr_SetString(PyExc_ImportError, errString); return NULL; } 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); return NULL; } theSym = NSLookupAndBindSymbol(funcname); p = (dl_funcptr)NSAddressOfSymbol(theSym); } #endif /* USE_DYLD */ return p; }