| |
| /* Support for dynamic loading of extension modules */ |
| |
| #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} |
| }; |
| |
| 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; |
| } |