dynload_next.c 3.42 KB
Newer Older
1

2 3 4
/* Support for dynamic loading of extension modules on Mac OS X
** All references to "NeXT" are for historical reasons.
*/
5 6 7 8 9 10 11 12 13 14 15 16

#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}
};

17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
/*
** 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
34
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
35
					const char *pathname, FILE *fp)
36 37
{
	dl_funcptr p = NULL;
38
	char funcname[258];
39 40 41 42 43 44
	NSObjectFileImageReturnCode rc;
	NSObjectFileImage image;
	NSModule newModule;
	NSSymbol theSym;
	const char *errString;
	char errBuf[512];
45

46
	PyOS_snprintf(funcname, sizeof(funcname), "_init%.200s", shortname);
47

48
#ifdef USE_DYLD_GLOBAL_NAMESPACE
49 50 51 52 53
	if (NSIsSymbolNameDefined(funcname)) {
		theSym = NSLookupAndBindSymbol(funcname);
		p = (dl_funcptr)NSAddressOfSymbol(theSym);
		return p;
	}
54
#endif
55 56 57 58 59
	rc = NSCreateObjectFileImageFromFile(pathname, &image);
	switch(rc) {
		default:
		case NSObjectFileImageFailure:
		case NSObjectFileImageFormat:
60
			/* for these a message is printed on stderr by dyld */
61
			errString = "Can't create object file image";
62 63
		break;
		case NSObjectFileImageSuccess:
64 65
			errString = NULL;
			break;
66
		case NSObjectFileImageInappropriateFile:
67 68
			errString = "Inappropriate file type for dynamic loading";
			break;
69
		case NSObjectFileImageArch:
70 71
			errString = "Wrong CPU type in object file";
			break;
72
		case NSObjectFileImageAccess:
73 74
			errString = "Can't read object file (no access)";
			break;
75 76 77 78 79
	}
	if (errString == NULL) {
		newModule = NSLinkModule(image, pathname, LINKOPTIONS);
		if (newModule == NULL) {
			int errNo;
80
			const char *fileName, *moreErrorStr;
81 82 83 84 85
			NSLinkEditErrors c;
			NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr );
			PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s", 
					fileName, moreErrorStr);
			errString = errBuf;
86
		}
87 88 89 90 91
	}
	if (errString != NULL) {
		PyErr_SetString(PyExc_ImportError, errString);
		return NULL;
	}
92
#ifdef USE_DYLD_GLOBAL_NAMESPACE
93 94
	if (!NSIsSymbolNameDefined(funcname)) {
		/* UnlinkModule() isn't implemented in current versions, but calling it does no harm */
95
		/* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
96 97 98 99 100 101
		PyErr_Format(PyExc_ImportError,
				 "Loaded module does not contain symbol %.200s",
				 funcname);
		return NULL;
	}
	theSym = NSLookupAndBindSymbol(funcname);
102
#else
103 104
	theSym = NSLookupSymbolInModule(newModule, funcname);
	if ( theSym == NULL ) {
105
		/* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
106 107 108 109
		PyErr_Format(PyExc_ImportError,
				 "Loaded module does not contain symbol %.200s",
				 funcname);
		return NULL;
110
	}
111 112
#endif
	p = (dl_funcptr)NSAddressOfSymbol(theSym);
113 114
	return p;
}