2 /* Support for dynamic loading of extension modules */
12 #include <mach-o/dyld.h>
17 /* Define this to 1 if you want be able to load ObjC modules as well:
18 it switches between two different way of loading modules on the NeXT,
19 one that directly interfaces with the dynamic loader (rld_load(), which
20 does not correctly load ObjC object files), and another that uses the
21 ObjC runtime (objc_loadModules()) to do the job.
22 You'll have to add ``-ObjC'' to the compiler flags if you set this to 1.
24 #define HANDLE_OBJC_MODULES 1
25 #if HANDLE_OBJC_MODULES
26 #include <objc/Object.h>
27 #include <objc/objc-load.h>
30 #include <mach-o/rld.h>
32 #endif /* WITH_DYLD */
35 const struct filedescr _PyImport_DynLoadFiletab
[] = {
36 {".so", "rb", C_EXTENSION
},
37 {"module.so", "rb", C_EXTENSION
},
41 dl_funcptr
_PyImport_GetDynLoadFunc(const char *fqname
, const char *shortname
,
42 const char *pathname
, FILE *fp
)
47 PyOS_snprintf(funcname
, sizeof(funcname
), "_init%.200s", shortname
);
51 NXStream
*errorStream
;
52 struct mach_header
*new_header
;
53 const char *filenames
[2];
57 errorStream
= NXOpenMemory(NULL
, 0, NX_WRITEONLY
);
58 filenames
[0] = pathname
;
61 #if HANDLE_OBJC_MODULES
63 /* The following very bogus line of code ensures that
64 objc_msgSend, etc are linked into the binary. Without
65 it, dynamic loading of a module that includes objective-c
66 method calls will fail with "undefined symbol _objc_msgSend()".
67 This remains true even in the presence of the -ObjC flag
73 /* objc_loadModules() dynamically loads the object files
74 indicated by the paths in filenames. If there are any
75 errors generated during loading -- typically due to the
76 inability to find particular symbols -- an error message
77 will be written to errorStream.
78 It returns 0 if the module is successfully loaded, 1
82 ret
= !objc_loadModules(filenames
, errorStream
,
83 NULL
, &new_header
, NULL
);
85 #else /* !HANDLE_OBJC_MODULES */
87 ret
= rld_load(errorStream
, &new_header
,
90 #endif /* HANDLE_OBJC_MODULES */
92 /* extract the error messages for the exception */
97 NXPutc(errorStream
, (char)0);
99 NXGetMemoryBuffer(errorStream
,
100 &streamBuf
, &len
, &maxLen
);
101 PyErr_SetString(PyExc_ImportError
, streamBuf
);
104 if(ret
&& rld_lookup(errorStream
, funcname
, &ptr
))
105 p
= (dl_funcptr
) ptr
;
107 NXCloseMemory(errorStream
, NX_FREEBUFFER
);
114 /* This is also NeXT-specific. However, frameworks (the new style
115 of shared library) and rld() can't be used in the same program;
116 instead, you have to use dyld, which is mostly unimplemented. */
118 NSObjectFileImageReturnCode rc
;
119 NSObjectFileImage image
;
122 const char *errString
;
124 if (NSIsSymbolNameDefined(funcname
)) {
125 theSym
= NSLookupAndBindSymbol(funcname
);
126 p
= (dl_funcptr
)NSAddressOfSymbol(theSym
);
129 rc
= NSCreateObjectFileImageFromFile(pathname
, &image
);
132 case NSObjectFileImageFailure
:
133 case NSObjectFileImageFormat
:
134 /* for these a message is printed on stderr by dyld */
135 errString
= "Can't create object file image";
137 case NSObjectFileImageSuccess
:
140 case NSObjectFileImageInappropriateFile
:
141 errString
= "Inappropriate file type for dynamic loading";
143 case NSObjectFileImageArch
:
144 errString
= "Wrong CPU type in object file";
146 case NSObjectFileImageAccess
:
147 errString
= "Can't read object file (no access)";
150 if (errString
== NULL
) {
151 newModule
= NSLinkModule(image
, pathname
,
152 NSLINKMODULE_OPTION_BINDNOW
|NSLINKMODULE_OPTION_RETURN_ON_ERROR
);
154 errString
= "Failure linking new module";
156 if (errString
!= NULL
) {
157 PyErr_SetString(PyExc_ImportError
, errString
);
160 if (!NSIsSymbolNameDefined(funcname
)) {
161 /* UnlinkModule() isn't implemented in current versions, but calling it does no harm */
162 NSUnLinkModule(newModule
, FALSE
);
163 PyErr_Format(PyExc_ImportError
,
164 "Loaded module does not contain symbol %.200s",
168 theSym
= NSLookupAndBindSymbol(funcname
);
169 p
= (dl_funcptr
)NSAddressOfSymbol(theSym
);
171 #endif /* USE_DYLD */