mirror of
				https://github.com/python/cpython.git
				synced 2025-10-25 02:43:41 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			169 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
 | |
| /* 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;
 | |
| }
 | 
