You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
3.3 KiB
113 lines
3.3 KiB
|
|
/* 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}, |
|
{".carbon.slb", "rb", C_EXTENSION}, |
|
{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; |
|
}
|
|
|