| |
| /* Support for dynamic loading of extension modules */ |
| |
| #include "Python.h" |
| #include "importdl.h" |
| |
| #include <Aliases.h> |
| #include <CodeFragments.h> |
| #ifdef USE_GUSI1 |
| #include "TFileSpec.h" /* for Path2FSSpec() */ |
| #endif |
| #include <Files.h> |
| #include <TextUtils.h> |
| #include "macdefs.h" |
| #include "macglue.h" |
| |
| |
| const struct filedescr _PyImport_DynLoadFiletab[] = { |
| {".slb", "rb", C_EXTENSION}, |
| #ifdef __CFM68K__ |
| {".CFM68K.slb", "rb", C_EXTENSION}, |
| #else |
| #if TARGET_API_MAC_CARBON |
| {".carbon.slb", "rb", C_EXTENSION}, |
| #else |
| {".ppc.slb", "rb", C_EXTENSION}, |
| #endif |
| #endif |
| {0, 0} |
| }; |
| |
| |
| dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, |
| const char *pathname, FILE *fp) |
| { |
| dl_funcptr p; |
| char funcname[258]; |
| |
| /* |
| ** Dynamic loading of CFM shared libraries on the Mac. The |
| ** code has become more convoluted than it was, because we |
| ** want to be able to put multiple modules in a single |
| ** file. For this reason, we have to determine the fragment |
| ** name, and we cannot use the library entry point but we have |
| ** to locate the correct init routine "by hand". |
| */ |
| FSSpec libspec; |
| CFragConnectionID connID; |
| Ptr mainAddr; |
| Str255 errMessage; |
| OSErr err; |
| #ifndef USE_GUSI1 |
| Boolean isfolder, didsomething; |
| #endif |
| char buf[512]; |
| Str63 fragname; |
| Ptr symAddr; |
| CFragSymbolClass class; |
| |
| /* First resolve any aliases to find the real file */ |
| #ifdef USE_GUSI1 |
| err = Path2FSSpec(pathname, &libspec); |
| #else |
| c2pstrcpy((unsigned char *)buf, pathname); |
| (void)FSMakeFSSpec(0, 0, (unsigned char *)buf, &libspec); |
| err = ResolveAliasFile(&libspec, 1, &isfolder, &didsomething); |
| #endif |
| if ( err ) { |
| PyOS_snprintf(buf, sizeof(buf), |
| "%.200s: %.200s", pathname, PyMac_StrError(err)); |
| PyErr_SetString(PyExc_ImportError, buf); |
| return NULL; |
| } |
| /* Next, determine the fragment name, |
| by stripping '.slb' and 'module' */ |
| memcpy(fragname+1, libspec.name+1, libspec.name[0]); |
| fragname[0] = libspec.name[0]; |
| if( strncmp((char *)(fragname+1+fragname[0]-4), |
| ".slb", 4) == 0 ) |
| fragname[0] -= 4; |
| if ( strncmp((char *)(fragname+1+fragname[0]-6), |
| "module", 6) == 0 ) |
| fragname[0] -= 6; |
| /* Load the fragment |
| (or return the connID if it is already loaded */ |
| err = GetDiskFragment(&libspec, 0, 0, fragname, |
| kLoadCFrag, &connID, &mainAddr, |
| errMessage); |
| if ( err == cfragImportTooOldErr || err == cfragImportTooNewErr ) { |
| /* |
| ** Special-case code: if PythonCore is too old or too new this means |
| ** the dynamic module was meant for a different Python. |
| */ |
| if (errMessage[0] == 10 && strncmp((char *)errMessage+1, "PythonCore", 10) == 0 ) { |
| PyOS_snprintf(buf, sizeof(buf), |
| "Dynamic module was built for %s version of MacPython", |
| (err == cfragImportTooOldErr ? "a newer" : "an older")); |
| PyErr_SetString(PyExc_ImportError, buf); |
| return NULL; |
| } |
| } |
| if ( err ) { |
| PyOS_snprintf(buf, sizeof(buf), "%.*s: %.200s", |
| errMessage[0], errMessage+1, |
| PyMac_StrError(err)); |
| PyErr_SetString(PyExc_ImportError, buf); |
| return NULL; |
| } |
| /* Locate the address of the correct init function */ |
| PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname); |
| err = FindSymbol(connID, Pstring(funcname), &symAddr, &class); |
| if ( err ) { |
| PyOS_snprintf(buf, sizeof(buf), "%s: %.200s", |
| funcname, PyMac_StrError(err)); |
| PyErr_SetString(PyExc_ImportError, buf); |
| return NULL; |
| } |
| p = (dl_funcptr)symAddr; |
| |
| return p; |
| } |