1. Armin Rigo
  2. cpython-withatomic


cpython-withatomic / Python / dynload_next.c

The branch 'legacy-trunk' does not exist.

/* 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.
#include <objc/Object.h>
#include <objc/objc-load.h>

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


/* 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

		ret = !objc_loadModules(filenames, errorStream,
					NULL, &new_header, NULL);


		ret = rld_load(errorStream, &new_header, 
				filenames, NULL);


		/* extract the error messages for the exception */
		if(!ret) {
			char *streamBuf;
			int len, maxLen;

			NXPutc(errorStream, (char)0);

				&streamBuf, &len, &maxLen);
			PyErr_SetString(PyExc_ImportError, streamBuf);

		if(ret && rld_lookup(errorStream, funcname, &ptr))
			p = (dl_funcptr) ptr;

		NXCloseMemory(errorStream, NX_FREEBUFFER);

			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) {
		    case NSObjectFileImageFailure:
		    /* for these a message is printed on stderr by dyld */
			errString = "Can't create object file image";
		    case NSObjectFileImageSuccess:
			errString = NULL;
		    case NSObjectFileImageInappropriateFile:
			errString = "Inappropriate file type for dynamic loading";
		    case NSObjectFileImageArch:
			errString = "Wrong CPU type in object file";
			errString = "Can't read object file (no access)";
		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);
				     "Loaded module does not contain symbol %.200s",
			return NULL;
		theSym = NSLookupAndBindSymbol(funcname);
		p = (dl_funcptr)NSAddressOfSymbol(theSym);
#endif /* USE_DYLD */

	return p;