| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* 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} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-12-22 14:09:35 +00:00
										 |  |  | dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | 				    const char *pathname, FILE *fp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	dl_funcptr p = NULL; | 
					
						
							| 
									
										
										
										
											1999-12-22 14:09:35 +00:00
										 |  |  | 	char funcname[258]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sprintf(funcname, "_init%.200s", shortname); | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #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)) { | 
					
						
							| 
									
										
										
										
											2000-07-16 12:04:32 +00:00
										 |  |  | 			/* UnlinkModule() isn't implemented in current versions, but calling it does no harm */ | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | 			NSUnLinkModule(newModule, FALSE); | 
					
						
							| 
									
										
										
										
											2000-04-10 12:46:51 +00:00
										 |  |  | 			PyErr_Format(PyExc_ImportError, | 
					
						
							|  |  |  | 				     "Loaded module does not contain symbol %.200s", | 
					
						
							|  |  |  | 				     funcname); | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		theSym = NSLookupAndBindSymbol(funcname); | 
					
						
							|  |  |  | 		p = (dl_funcptr)NSAddressOfSymbol(theSym); | 
					
						
							|  |  |  |  	} | 
					
						
							|  |  |  | #endif /* USE_DYLD */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return p; | 
					
						
							|  |  |  | } |